Salome HOME
HAVE_NETGEN (#define) to remove an unresolved symbol when building without netgen
[modules/smesh.git] / src / SMESH / SMESH_MEFISTO_2D.cxx
1 //  SMESH SMESH : implementaion of SMESH idl descriptions
2 //
3 //  Copyright (C) 2003  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS 
5 // 
6 //  This library is free software; you can redistribute it and/or 
7 //  modify it under the terms of the GNU Lesser General Public 
8 //  License as published by the Free Software Foundation; either 
9 //  version 2.1 of the License. 
10 // 
11 //  This library is distributed in the hope that it will be useful, 
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of 
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
14 //  Lesser General Public License for more details. 
15 // 
16 //  You should have received a copy of the GNU Lesser General Public 
17 //  License along with this library; if not, write to the Free Software 
18 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA 
19 // 
20 //  See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org 
21 //
22 //
23 //
24 //  File   : SMESH_MEFISTO_2D.cxx
25 //  Author : Paul RASCLE, EDF
26 //  Module : SMESH
27 //  $Header$
28
29 using namespace std;
30 #include "SMESH_MEFISTO_2D.hxx"
31 #include "SMESH_Gen.hxx"
32 #include "SMESH_Mesh.hxx"
33
34 #include "SMESH_MaxElementArea.hxx"
35 #include "SMESH_LengthFromEdges.hxx"
36
37 #include "Rn.h"
38 #include "aptrte.h"
39
40 #include "SMDS_MeshElement.hxx"
41 #include "SMDS_MeshNode.hxx"
42 #include "SMDS_EdgePosition.hxx"
43 #include "SMDS_FacePosition.hxx"
44
45 #include "utilities.h"
46
47 #include <TopoDS_Face.hxx>
48 #include <TopoDS_Edge.hxx>
49 #include <TopoDS_Shape.hxx>
50 #include <Geom_Surface.hxx>
51 #include <GeomAdaptor_Curve.hxx>
52 #include <Geom2d_Curve.hxx>
53 #include <gp_Pnt2d.hxx>
54 #include <BRep_Tool.hxx>
55 #include <BRepTools.hxx>
56 #include <BRepTools_WireExplorer.hxx>
57 #include <GCPnts_AbscissaPoint.hxx>
58 #include <GCPnts_UniformAbscissa.hxx>
59 #include <TColStd_ListIteratorOfListOfInteger.hxx>
60
61 #include <string>
62 #include <algorithm>
63
64 //=============================================================================
65 /*!
66  *  
67  */
68 //=============================================================================
69
70 SMESH_MEFISTO_2D::SMESH_MEFISTO_2D(int hypId, int studyId,
71         SMESH_Gen * gen):SMESH_2D_Algo(hypId, studyId, gen)
72 {
73         MESSAGE("SMESH_MEFISTO_2D::SMESH_MEFISTO_2D");
74         _name = "MEFISTO_2D";
75 //   _shapeType = TopAbs_FACE;
76         _shapeType = (1 << TopAbs_FACE);
77         _compatibleHypothesis.push_back("MaxElementArea");
78         _compatibleHypothesis.push_back("LengthFromEdges");
79
80         _edgeLength = 0;
81         _maxElementArea = 0;
82         _hypMaxElementArea = NULL;
83         _hypLengthFromEdges = NULL;
84 }
85
86 //=============================================================================
87 /*!
88  *  
89  */
90 //=============================================================================
91
92 SMESH_MEFISTO_2D::~SMESH_MEFISTO_2D()
93 {
94         MESSAGE("SMESH_MEFISTO_2D::~SMESH_MEFISTO_2D");
95 }
96
97 //=============================================================================
98 /*!
99  *  
100  */
101 //=============================================================================
102
103 bool SMESH_MEFISTO_2D::CheckHypothesis(SMESH_Mesh & aMesh,
104         const TopoDS_Shape & aShape)
105 {
106         //MESSAGE("SMESH_MEFISTO_2D::CheckHypothesis");
107
108         _hypMaxElementArea = NULL;
109         _hypLengthFromEdges = NULL;
110
111         list <const SMESHDS_Hypothesis * >::const_iterator itl;
112         const SMESHDS_Hypothesis *theHyp;
113
114         const list <const SMESHDS_Hypothesis * >&hyps = GetUsedHypothesis(aMesh, aShape);
115         int nbHyp = hyps.size();
116         if (nbHyp != 1) return false;// only one compatible hypothesis allowed
117
118         itl = hyps.begin();
119         theHyp = (*itl);
120
121         string hypName = theHyp->GetName();
122         int hypId = theHyp->GetID();
123         //SCRUTE(hypName);
124
125         bool isOk = false;
126
127         if (hypName == "MaxElementArea")
128         {
129                 _hypMaxElementArea = static_cast<const SMESH_MaxElementArea *>(theHyp);
130                 ASSERT(_hypMaxElementArea);
131                 _maxElementArea = _hypMaxElementArea->GetMaxArea();
132                 _edgeLength = 0;
133                 isOk = true;
134         }
135
136         if (hypName == "LengthFromEdges")
137         {
138                 _hypLengthFromEdges = static_cast<const SMESH_LengthFromEdges *>(theHyp);
139                 ASSERT(_hypLengthFromEdges);
140                 _edgeLength = 0;
141                 _maxElementArea = 0;
142                 isOk = true;
143         }
144
145         if (isOk)
146         {
147                 isOk = false;
148                 if (_maxElementArea > 0)
149                 {
150                         _edgeLength = 2 * sqrt(_maxElementArea);        // triangles : minorant
151                         isOk = true;
152                 }
153                 else
154                         isOk = (_hypLengthFromEdges != NULL);   // **** check mode
155         }
156
157         //SCRUTE(_edgeLength);
158         //SCRUTE(_maxElementArea);
159         return isOk;
160 }
161
162 //=============================================================================
163 /*!
164  *  
165  */
166 //=============================================================================
167
168 bool SMESH_MEFISTO_2D::Compute(SMESH_Mesh & aMesh, const TopoDS_Shape & aShape)
169 {
170         MESSAGE("SMESH_MEFISTO_2D::Compute");
171
172         if (_hypLengthFromEdges)
173                 _edgeLength = ComputeEdgeElementLength(aMesh, aShape);
174
175         bool isOk = false;
176         const SMESHDS_Mesh * meshDS = aMesh.GetMeshDS();
177         SMESH_subMesh *theSubMesh = aMesh.GetSubMesh(aShape);
178
179         const TopoDS_Face & FF = TopoDS::Face(aShape);
180         bool faceIsForward = (FF.Orientation() == TopAbs_FORWARD);
181         TopoDS_Face F = TopoDS::Face(FF.Oriented(TopAbs_FORWARD));
182
183         Z nblf;                                         //nombre de lignes fermees (enveloppe en tete)
184         Z *nudslf = NULL;                       //numero du dernier sommet de chaque ligne fermee
185         R2 *uvslf = NULL;
186         Z nbpti = 0;                            //nombre points internes futurs sommets de la triangulation
187         R2 *uvpti = NULL;
188
189         Z nbst;
190         R2 *uvst = NULL;
191         Z nbt;
192         Z *nust = NULL;
193         Z ierr = 0;
194
195         Z nutysu = 1;                           // 1: il existe un fonction areteideale_()
196         // Z  nutysu=0;              // 0: on utilise aretmx
197         R aretmx = _edgeLength;         // longueur max aretes future triangulation
198         //SCRUTE(aretmx);
199
200         nblf = NumberOfWires(F);
201         //SCRUTE(nblf);
202
203         nudslf = new Z[1 + nblf];
204         nudslf[0] = 0;
205         int iw = 1;
206         int nbpnt = 0;
207
208         const TopoDS_Wire OW1 = BRepTools::OuterWire(F);
209         nbpnt += NumberOfPoints(aMesh, OW1);
210         nudslf[iw++] = nbpnt;
211         //SCRUTE(nbpnt);
212
213         for (TopExp_Explorer exp(F, TopAbs_WIRE); exp.More(); exp.Next())
214         {
215                 const TopoDS_Wire & W = TopoDS::Wire(exp.Current());
216                 if (!OW1.IsSame(W))
217                 {
218                         nbpnt += NumberOfPoints(aMesh, W);
219                         nudslf[iw++] = nbpnt;
220                         //SCRUTE(nbpnt);
221                 }
222         }
223
224         uvslf = new R2[nudslf[nblf]];
225         //SCRUTE(nudslf[nblf]);
226         int m = 0;
227
228         map<int, const SMDS_MeshNode*> mefistoToDS;     // correspondence mefisto index--> points IDNodes
229         TopoDS_Wire OW = BRepTools::OuterWire(F);
230         LoadPoints(aMesh, F, OW, uvslf, m, mefistoToDS);
231         //SCRUTE(m);
232
233         for (TopExp_Explorer exp(F, TopAbs_WIRE); exp.More(); exp.Next())
234         {
235                 const TopoDS_Wire & W = TopoDS::Wire(exp.Current());
236                 if (!OW.IsSame(W))
237                 {
238                         LoadPoints(aMesh, F, W, uvslf, m, mefistoToDS);
239                         //SCRUTE(m);
240                 }
241         }
242 //   SCRUTE(nudslf[nblf]);
243 //   for (int i=0; i<=nblf; i++)
244 //     {
245 //       MESSAGE(" -+- " <<i<< " "<< nudslf[i]);
246 //     }
247 //   for (int i=0; i<nudslf[nblf]; i++)
248 //     {
249 //       MESSAGE(" -+- " <<i<< " "<< uvslf[i]);
250 //     }
251 //   SCRUTE(nutysu);
252 //   SCRUTE(aretmx);
253 //   SCRUTE(nblf);
254
255         MESSAGE("MEFISTO triangulation ...");
256         uvst = NULL;
257         nust = NULL;
258         aptrte(nutysu, aretmx,
259                 nblf, nudslf, uvslf, nbpti, uvpti, nbst, uvst, nbt, nust, ierr);
260
261         if (ierr == 0)
262           {
263             MESSAGE("... End Triangulation Generated Triangle Number " << nbt);
264             MESSAGE("                                    Node Number " << nbst);
265             //SCRUTE(nbst);
266             //SCRUTE(nbt);
267             StoreResult(aMesh, nbst, uvst, nbt, nust, F,
268                         faceIsForward, mefistoToDS);
269             isOk = true;
270           }
271         else
272         {
273                 MESSAGE("Error in Triangulation");
274                 isOk = false;
275         }
276         if (nudslf != NULL)
277                 delete[]nudslf;
278         if (uvslf != NULL)
279                 delete[]uvslf;
280         if (uvst != NULL)
281                 delete[]uvst;
282         if (nust != NULL)
283                 delete[]nust;
284         return isOk;
285 }
286
287 //=============================================================================
288 /*!
289  *  
290  */
291 //=============================================================================
292
293 void SMESH_MEFISTO_2D::LoadPoints(SMESH_Mesh & aMesh,
294         const TopoDS_Face & FF,
295         const TopoDS_Wire & WW, R2 * uvslf, int &m,
296         map<int, const SMDS_MeshNode*>&mefistoToDS)
297 {
298         MESSAGE("SMESH_MEFISTO_2D::LoadPoints");
299
300         SMDS_Mesh * meshDS = aMesh.GetMeshDS();
301
302         double scalex;
303         double scaley;
304         TopoDS_Face F = TopoDS::Face(FF.Oriented(TopAbs_FORWARD));
305         ComputeScaleOnFace(aMesh, F, scalex, scaley);
306
307         TopoDS_Wire W = TopoDS::Wire(WW.Oriented(TopAbs_FORWARD));
308         BRepTools_WireExplorer wexp(W, F);
309         for (wexp.Init(W, F); wexp.More(); wexp.Next())
310         {
311                 const TopoDS_Edge & E = wexp.Current();
312
313                 // --- IDNodes of first and last Vertex
314
315                 TopoDS_Vertex VFirst, VLast;
316                 TopExp::Vertices(E, VFirst, VLast);     // corresponds to f and l
317
318             ASSERT(!VFirst.IsNull());
319                 SMDS_Iterator<const SMDS_MeshNode *> * lid=
320                 aMesh.GetSubMesh(VFirst)->GetSubMeshDS()->GetNodes();
321                 const SMDS_MeshNode* idFirst = lid->next();
322                 delete lid;
323
324                 ASSERT(!VLast.IsNull());
325                 lid=aMesh.GetSubMesh(VLast)->GetSubMeshDS()->GetNodes();
326                 const SMDS_MeshNode* idLast = lid->next();
327                 delete lid;
328
329                 // --- edge internal IDNodes (relies on good order storage, not checked)
330
331                 int nbPoints = aMesh.GetSubMesh(E)->GetSubMeshDS()->NbNodes();
332                 //SCRUTE(nbPoints);
333
334                 double f, l;
335                 Handle(Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface(E, F, f, l);
336
337                 SMDS_Iterator<const SMDS_MeshNode *> * ite=
338                         aMesh.GetSubMesh(E)->GetSubMeshDS()->GetNodes();
339
340                 bool isForward = (E.Orientation() == TopAbs_FORWARD);
341                 map<double, const SMDS_MeshNode*> params;
342
343                 while(ite->more())
344                 {
345                         const SMDS_MeshNode * node = ite->next();
346                         const SMDS_EdgePosition* epos
347                                 = static_cast<const SMDS_EdgePosition*>(node->GetPosition());
348                         double param = epos->GetUParameter();
349                         params[param] = node;
350                 }
351                 delete ite;
352                 // --- load 2D values into MEFISTO structure,
353                 //     add IDNodes in mefistoToDS map
354
355                 if (E.Orientation() == TopAbs_FORWARD)
356                 {
357                         gp_Pnt2d p = C2d->Value(f);     // first point = Vertex Forward
358                         uvslf[m].x = scalex * p.X();
359                         uvslf[m].y = scaley * p.Y();
360                         mefistoToDS[m + 1] = idFirst;
361                         //MESSAGE(" "<<m<<" "<<mefistoToDS[m+1]);
362                         //MESSAGE("__ f "<<f<<" "<<uvslf[m].x <<" "<<uvslf[m].y);
363                         m++;
364                         map<double, const SMDS_MeshNode*>::iterator itp = params.begin();
365                         for (int i = 1; i <= nbPoints; i++)     // nbPoints internal
366                         {
367                                 double param = (*itp).first;
368                                 gp_Pnt2d p = C2d->Value(param);
369                                 uvslf[m].x = scalex * p.X();
370                                 uvslf[m].y = scaley * p.Y();
371                                 mefistoToDS[m + 1] = (*itp).second;
372 //        MESSAGE(" "<<m<<" "<<mefistoToDS[m+1]);
373 //        MESSAGE("__ "<<i<<" "<<param<<" "<<uvslf[m].x <<" "<<uvslf[m].y);
374                                 m++;
375                                 itp++;
376                         }
377                 }
378                 else
379                 {
380                         gp_Pnt2d p = C2d->Value(l);     // last point = Vertex Reversed
381                         uvslf[m].x = scalex * p.X();
382                         uvslf[m].y = scaley * p.Y();
383                         mefistoToDS[m + 1] = idLast;
384 //    MESSAGE(" "<<m<<" "<<mefistoToDS[m+1]);
385 //    MESSAGE("__ l "<<l<<" "<<uvslf[m].x <<" "<<uvslf[m].y);
386                         m++;
387                         map<double, const SMDS_MeshNode*>::reverse_iterator itp = params.rbegin();
388                         for (int i = nbPoints; i >= 1; i--)
389                         {
390                                 double param = (*itp).first;
391                                 gp_Pnt2d p = C2d->Value(param);
392                                 uvslf[m].x = scalex * p.X();
393                                 uvslf[m].y = scaley * p.Y();
394                                 mefistoToDS[m + 1] = (*itp).second;
395 //        MESSAGE(" "<<m<<" "<<mefistoToDS[m+1]);
396 //            MESSAGE("__ "<<i<<" "<<param<<" "<<uvslf[m].x <<" "<<uvslf[m].y);
397                                 m++;
398                                 itp++;
399                         }
400                 }
401         }
402 }
403
404 //=============================================================================
405 /*!
406  *  
407  */
408 //=============================================================================
409
410 // **** a mettre dans SMESH_Algo ou SMESH_2D_Algo
411
412 void SMESH_MEFISTO_2D::ComputeScaleOnFace(SMESH_Mesh & aMesh,
413         const TopoDS_Face & aFace, double &scalex, double &scaley)
414 {
415         //MESSAGE("SMESH_MEFISTO_2D::ComputeScaleOnFace");
416         TopoDS_Face F = TopoDS::Face(aFace.Oriented(TopAbs_FORWARD));
417         TopoDS_Wire W = BRepTools::OuterWire(F);
418
419         BRepTools_WireExplorer wexp(W, F);
420
421         double xmin = 1.e300;           // min & max of face 2D parametric coord.
422         double xmax = -1.e300;
423         double ymin = 1.e300;
424         double ymax = -1.e300;
425         int nbp = 50;
426         scalex = 1;
427         scaley = 1;
428         for (wexp.Init(W, F); wexp.More(); wexp.Next())
429         {
430                 const TopoDS_Edge & E = wexp.Current();
431                 double f, l;
432                 Handle(Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface(E, F, f, l);
433                 for (int i = 0; i <= nbp; i++)
434                 {
435                         double param = f + (double (i) / double (nbp))*(l - f);
436                         gp_Pnt2d p = C2d->Value(param);
437                         if (p.X() < xmin)
438                                 xmin = p.X();
439                         if (p.X() > xmax)
440                                 xmax = p.X();
441                         if (p.Y() < ymin)
442                                 ymin = p.Y();
443                         if (p.Y() > ymax)
444                                 ymax = p.Y();
445 //    MESSAGE(" "<< f<<" "<<l<<" "<<param<<" "<<xmin<<" "<<xmax<<" "<<ymin<<" "<<ymax);
446                 }
447         }
448 //   SCRUTE(xmin);
449 //   SCRUTE(xmax);
450 //   SCRUTE(ymin);
451 //   SCRUTE(ymax);
452         double xmoy = (xmax + xmin) / 2.;
453         double ymoy = (ymax + ymin) / 2.;
454
455         Handle(Geom_Surface) S = BRep_Tool::Surface(F); // 3D surface
456
457         double length_x = 0;
458         double length_y = 0;
459         gp_Pnt PX0 = S->Value(xmin, ymoy);
460         gp_Pnt PY0 = S->Value(xmoy, ymin);
461         for (int i = 1; i <= nbp; i++)
462         {
463                 double x = xmin + (double (i) / double (nbp))*(xmax - xmin);
464                 gp_Pnt PX = S->Value(x, ymoy);
465                 double y = ymin + (double (i) / double (nbp))*(ymax - ymin);
466                 gp_Pnt PY = S->Value(xmoy, y);
467                 length_x += PX.Distance(PX0);
468                 length_y += PY.Distance(PY0);
469                 PX0.SetCoord(PX.X(), PX.Y(), PX.Z());
470                 PY0.SetCoord(PY.X(), PY.Y(), PY.Z());
471         }
472 //   SCRUTE(length_x);
473 //   SCRUTE(length_y);
474         scalex = length_x / (xmax - xmin);
475         scaley = length_y / (ymax - ymin);
476 //   SCRUTE(scalex);
477 //   SCRUTE(scaley);
478         ASSERT(scalex);
479         ASSERT(scaley);
480 }
481
482 //=============================================================================
483 /*!
484  *  
485  */
486 //=============================================================================
487
488 void SMESH_MEFISTO_2D::StoreResult(SMESH_Mesh & aMesh,
489         Z nbst, R2 * uvst, Z nbt, Z * nust,
490         const TopoDS_Face & F, bool faceIsForward,
491         map<int, const SMDS_MeshNode*>&mefistoToDS)
492 {
493         double scalex;
494         double scaley;
495         ComputeScaleOnFace(aMesh, F, scalex, scaley);
496
497         SMESHDS_Mesh * meshDS = aMesh.GetMeshDS();
498
499         Z n, m;
500         Handle(Geom_Surface) S = BRep_Tool::Surface(F);
501
502         for (n = 0; n < nbst; n++)
503         {
504                 double u = uvst[n][0] / scalex;
505                 double v = uvst[n][1] / scaley;
506                 gp_Pnt P = S->Value(u, v);
507
508                 if (mefistoToDS.find(n + 1) == mefistoToDS.end())
509                 {
510                         SMDS_MeshNode * node = meshDS->AddNode(P.X(), P.Y(), P.Z());
511                         meshDS->SetNodeOnFace(node, F);
512
513                         //MESSAGE(nodeId<<" "<<P.X()<<" "<<P.Y()<<" "<<P.Z());
514                         mefistoToDS[n + 1] = node;
515                         //MESSAGE(" "<<n<<" "<<mefistoToDS[n+1]);
516                         SMDS_FacePosition* fpos
517                                 = static_cast<SMDS_FacePosition*>(node->GetPosition());
518                         fpos->SetUParameter(u);
519                         fpos->SetVParameter(v);
520                 }
521         }
522
523         m = 0;
524         int mt = 0;
525
526         //SCRUTE(faceIsForward);
527         for (n = 1; n <= nbt; n++)
528         {
529                 int inode1 = nust[m++];
530                 int inode2 = nust[m++];
531                 int inode3 = nust[m++];
532
533                 const SMDS_MeshNode *n1, *n2, *n3;
534                 n1 = mefistoToDS[inode1];
535                 n2 = mefistoToDS[inode2];
536                 n3 = mefistoToDS[inode3];
537                 //MESSAGE("-- "<<inode1<<" "<<inode2<<" "<<inode3<<" ++ "<<nodeId1<<" "<<nodeId2<<" "<<nodeId3);
538
539                 // triangle points must be in trigonometric order if face is Forward
540                 // else they must be put clockwise
541
542                 bool triangleIsWellOriented = faceIsForward;
543
544         SMDS_MeshElement * elt;
545                 if (triangleIsWellOriented)
546                         elt = meshDS->AddFace(n1, n2, n3);
547                 else
548                         elt = meshDS->AddFace(n1, n3, n2);
549         
550                 meshDS->SetMeshElementOnShape(elt, F);
551                 m++;
552         }
553 }
554
555 //=============================================================================
556 /*!
557  *  
558  */
559 //=============================================================================
560
561 double SMESH_MEFISTO_2D::ComputeEdgeElementLength(SMESH_Mesh & aMesh,
562         const TopoDS_Shape & aShape)
563 {
564         MESSAGE("SMESH_MEFISTO_2D::ComputeEdgeElementLength");
565         // **** a mettre dans SMESH_2D_Algo ?
566
567         const TopoDS_Face & FF = TopoDS::Face(aShape);
568         bool faceIsForward = (FF.Orientation() == TopAbs_FORWARD);
569         TopoDS_Face F = TopoDS::Face(FF.Oriented(TopAbs_FORWARD));
570
571         double meanElementLength = 100;
572         double wireLength = 0;
573         int wireElementsNumber = 0;
574         for (TopExp_Explorer exp(F, TopAbs_WIRE); exp.More(); exp.Next())
575         {
576                 const TopoDS_Wire & W = TopoDS::Wire(exp.Current());
577                 for (TopExp_Explorer expe(W, TopAbs_EDGE); expe.More(); expe.Next())
578                 {
579                         const TopoDS_Edge & E = TopoDS::Edge(expe.Current());
580                         int nb = aMesh.GetSubMesh(E)->GetSubMeshDS()->NbNodes();
581                         double length = EdgeLength(E);
582                         wireLength += length;
583                         wireElementsNumber += nb;
584                 }
585         }
586         if (wireElementsNumber)
587                 meanElementLength = wireLength / wireElementsNumber;
588         //SCRUTE(meanElementLength);
589         return meanElementLength;
590 }
591
592 //=============================================================================
593 /*!
594  *  
595  */
596 //=============================================================================
597
598 ostream & SMESH_MEFISTO_2D::SaveTo(ostream & save)
599 {
600         return save << this;
601 }
602
603 //=============================================================================
604 /*!
605  *  
606  */
607 //=============================================================================
608
609 istream & SMESH_MEFISTO_2D::LoadFrom(istream & load)
610 {
611         return load >> (*this);
612 }
613
614 //=============================================================================
615 /*!
616  *  
617  */
618 //=============================================================================
619
620 ostream & operator <<(ostream & save, SMESH_MEFISTO_2D & hyp)
621 {
622         return save;
623 }
624
625 //=============================================================================
626 /*!
627  *  
628  */
629 //=============================================================================
630
631 istream & operator >>(istream & load, SMESH_MEFISTO_2D & hyp)
632 {
633         return load;
634 }