1 // SMESH SMESH : implementaion of SMESH idl descriptions
3 // Copyright (C) 2003 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
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.
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.
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
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
24 // File : StdMeshers_Regular_1D.cxx
25 // Moved here from SMESH_Regular_1D.cxx
26 // Author : Paul RASCLE, EDF
32 #include "StdMeshers_Regular_1D.hxx"
33 #include "StdMeshers_Distribution.hxx"
35 #include "StdMeshers_LocalLength.hxx"
36 #include "StdMeshers_NumberOfSegments.hxx"
37 #include "StdMeshers_Arithmetic1D.hxx"
38 #include "StdMeshers_StartEndLength.hxx"
39 #include "StdMeshers_Deflection1D.hxx"
40 #include "StdMeshers_AutomaticLength.hxx"
42 #include "SMESH_Gen.hxx"
43 #include "SMESH_Mesh.hxx"
44 #include "SMESH_HypoFilter.hxx"
45 #include "SMESH_subMesh.hxx"
47 #include "SMDS_MeshElement.hxx"
48 #include "SMDS_MeshNode.hxx"
49 #include "SMDS_EdgePosition.hxx"
51 #include "Utils_SALOME_Exception.hxx"
52 #include "utilities.h"
54 #include <BRep_Tool.hxx>
55 #include <TopoDS_Edge.hxx>
56 #include <TopoDS_Shape.hxx>
57 #include <TopTools_ListIteratorOfListOfShape.hxx>
58 #include <GeomAdaptor_Curve.hxx>
59 #include <GCPnts_AbscissaPoint.hxx>
60 #include <GCPnts_UniformAbscissa.hxx>
61 #include <GCPnts_UniformDeflection.hxx>
62 #include <Precision.hxx>
63 #include <Expr_GeneralExpression.hxx>
64 #include <Expr_NamedUnknown.hxx>
65 #include <Expr_Array1OfNamedUnknown.hxx>
66 #include <ExprIntrp_GenExp.hxx>
67 #include <TColStd_Array1OfReal.hxx>
70 #include <Standard_ErrorHandler.hxx>
71 #include <Standard_Failure.hxx>
78 //=============================================================================
82 //=============================================================================
84 StdMeshers_Regular_1D::StdMeshers_Regular_1D(int hypId, int studyId,
85 SMESH_Gen * gen):SMESH_1D_Algo(hypId, studyId, gen)
87 MESSAGE("StdMeshers_Regular_1D::StdMeshers_Regular_1D");
89 _shapeType = (1 << TopAbs_EDGE);
91 _compatibleHypothesis.push_back("LocalLength");
92 _compatibleHypothesis.push_back("NumberOfSegments");
93 _compatibleHypothesis.push_back("StartEndLength");
94 _compatibleHypothesis.push_back("Deflection1D");
95 _compatibleHypothesis.push_back("Arithmetic1D");
96 _compatibleHypothesis.push_back("AutomaticLength");
98 _compatibleHypothesis.push_back("QuadraticMesh"); // auxiliary !!!
101 //=============================================================================
105 //=============================================================================
107 StdMeshers_Regular_1D::~StdMeshers_Regular_1D()
111 //=============================================================================
115 //=============================================================================
117 bool StdMeshers_Regular_1D::CheckHypothesis
119 const TopoDS_Shape& aShape,
120 SMESH_Hypothesis::Hypothesis_Status& aStatus)
123 _quadraticMesh = false;
125 const bool ignoreAuxiliaryHyps = false;
126 const list <const SMESHDS_Hypothesis * > & hyps =
127 GetUsedHypothesis(aMesh, aShape, ignoreAuxiliaryHyps);
129 // find non-auxiliary hypothesis
130 const SMESHDS_Hypothesis *theHyp = 0;
131 list <const SMESHDS_Hypothesis * >::const_iterator h = hyps.begin();
132 for ( ; h != hyps.end(); ++h ) {
133 if ( static_cast<const SMESH_Hypothesis*>(*h)->IsAuxiliary() ) {
134 if ( strcmp( "QuadraticMesh", (*h)->GetName() ) == 0 )
135 _quadraticMesh = true;
139 theHyp = *h; // use only the first non-auxiliary hypothesis
145 aStatus = SMESH_Hypothesis::HYP_MISSING;
146 return false; // can't work without a hypothesis
149 string hypName = theHyp->GetName();
151 if (hypName == "LocalLength")
153 const StdMeshers_LocalLength * hyp =
154 dynamic_cast <const StdMeshers_LocalLength * >(theHyp);
156 _value[ BEG_LENGTH_IND ] = _value[ END_LENGTH_IND ] = hyp->GetLength();
157 ASSERT( _value[ BEG_LENGTH_IND ] > 0 );
158 _hypType = LOCAL_LENGTH;
159 aStatus = SMESH_Hypothesis::HYP_OK;
162 else if (hypName == "NumberOfSegments")
164 const StdMeshers_NumberOfSegments * hyp =
165 dynamic_cast <const StdMeshers_NumberOfSegments * >(theHyp);
167 _ivalue[ NB_SEGMENTS_IND ] = hyp->GetNumberOfSegments();
168 ASSERT( _ivalue[ NB_SEGMENTS_IND ] > 0 );
169 _ivalue[ DISTR_TYPE_IND ] = (int) hyp->GetDistrType();
170 switch (_ivalue[ DISTR_TYPE_IND ])
172 case StdMeshers_NumberOfSegments::DT_Scale:
173 _value[ SCALE_FACTOR_IND ] = hyp->GetScaleFactor();
175 case StdMeshers_NumberOfSegments::DT_TabFunc:
176 _vvalue[ TAB_FUNC_IND ] = hyp->GetTableFunction();
178 case StdMeshers_NumberOfSegments::DT_ExprFunc:
179 _svalue[ EXPR_FUNC_IND ] = hyp->GetExpressionFunction();
181 case StdMeshers_NumberOfSegments::DT_Regular:
187 if (_ivalue[ DISTR_TYPE_IND ] == StdMeshers_NumberOfSegments::DT_TabFunc ||
188 _ivalue[ DISTR_TYPE_IND ] == StdMeshers_NumberOfSegments::DT_ExprFunc)
189 _ivalue[ CONV_MODE_IND ] = hyp->ConversionMode();
190 _hypType = NB_SEGMENTS;
191 aStatus = SMESH_Hypothesis::HYP_OK;
194 else if (hypName == "Arithmetic1D")
196 const StdMeshers_Arithmetic1D * hyp =
197 dynamic_cast <const StdMeshers_Arithmetic1D * >(theHyp);
199 _value[ BEG_LENGTH_IND ] = hyp->GetLength( true );
200 _value[ END_LENGTH_IND ] = hyp->GetLength( false );
201 ASSERT( _value[ BEG_LENGTH_IND ] > 0 && _value[ END_LENGTH_IND ] > 0 );
202 _hypType = ARITHMETIC_1D;
203 aStatus = SMESH_Hypothesis::HYP_OK;
206 else if (hypName == "StartEndLength")
208 const StdMeshers_StartEndLength * hyp =
209 dynamic_cast <const StdMeshers_StartEndLength * >(theHyp);
211 _value[ BEG_LENGTH_IND ] = hyp->GetLength( true );
212 _value[ END_LENGTH_IND ] = hyp->GetLength( false );
213 ASSERT( _value[ BEG_LENGTH_IND ] > 0 && _value[ END_LENGTH_IND ] > 0 );
214 _hypType = BEG_END_LENGTH;
215 aStatus = SMESH_Hypothesis::HYP_OK;
218 else if (hypName == "Deflection1D")
220 const StdMeshers_Deflection1D * hyp =
221 dynamic_cast <const StdMeshers_Deflection1D * >(theHyp);
223 _value[ DEFLECTION_IND ] = hyp->GetDeflection();
224 ASSERT( _value[ DEFLECTION_IND ] > 0 );
225 _hypType = DEFLECTION;
226 aStatus = SMESH_Hypothesis::HYP_OK;
229 else if (hypName == "AutomaticLength")
231 StdMeshers_AutomaticLength * hyp = const_cast<StdMeshers_AutomaticLength *>
232 (dynamic_cast <const StdMeshers_AutomaticLength * >(theHyp));
234 _value[ BEG_LENGTH_IND ] = _value[ END_LENGTH_IND ] = hyp->GetLength( &aMesh, aShape );
235 ASSERT( _value[ BEG_LENGTH_IND ] > 0 );
236 _hypType = LOCAL_LENGTH;
237 aStatus = SMESH_Hypothesis::HYP_OK;
240 aStatus = SMESH_Hypothesis::HYP_INCOMPATIBLE;
242 return ( _hypType != NONE );
245 //=======================================================================
246 //function : compensateError
247 //purpose : adjust theParams so that the last segment length == an
248 //=======================================================================
250 static void compensateError(double a1, double an,
251 double U1, double Un,
253 GeomAdaptor_Curve& C3d,
254 list<double> & theParams)
256 int i, nPar = theParams.size();
257 if ( a1 + an < length && nPar > 1 )
259 list<double>::reverse_iterator itU = theParams.rbegin();
261 // dist from the last point to the edge end <Un>, it should be equal <an>
262 double Ln = GCPnts_AbscissaPoint::Length( C3d, Ul, Un );
263 double dLn = an - Ln; // error of <an>
264 if ( Abs( dLn ) <= Precision::Confusion() )
266 double dU = Abs( Ul - *itU ); // parametric length of the last but one segment
267 double dUn = dLn * Abs( Un - U1 ) / length; // parametric error of <an>
268 if ( dUn < 0.5 * dU ) { // last segment is a bit shorter than it should
269 dUn = -dUn; // move the last parameter to the edge beginning
271 else { // last segment is much shorter than it should -> remove the last param and
272 theParams.pop_back(); nPar--; // move the rest points toward the edge end
273 Ln = GCPnts_AbscissaPoint::Length( C3d, theParams.back(), Un );
274 dUn = ( an - Ln ) * Abs( Un - U1 ) / length;
275 if ( dUn < 0.5 * dU )
280 double q = dUn / ( nPar - 1 );
281 for ( itU = theParams.rbegin(), i = 1; i < nPar; itU++, i++ ) {
288 static bool computeParamByFunc(Adaptor3d_Curve& C3d, double first, double last,
289 double length, bool theReverse,
290 int nbSeg, Function& func,
291 list<double>& theParams)
294 //OSD::SetSignal( true );
299 MESSAGE( "computeParamByFunc" );
301 int nbPnt = 1 + nbSeg;
302 vector<double> x(nbPnt, 0.);
304 if( !buildDistribution( func, 0.0, 1.0, nbSeg, x, 1E-4 ) )
307 MESSAGE( "Points:\n" );
309 for( int i=0; i<=nbSeg; i++ )
311 sprintf( buf, "%f\n", float(x[i] ) );
317 // apply parameters in range [0,1] to the space of the curve
318 double prevU = first;
325 for( int i = 1; i < nbSeg; i++ )
327 double curvLength = length * (x[i] - x[i-1]) * sign;
328 GCPnts_AbscissaPoint Discret( C3d, curvLength, prevU );
329 if ( !Discret.IsDone() )
331 double U = Discret.Parameter();
332 if ( U > first && U < last )
333 theParams.push_back( U );
341 //=============================================================================
345 //=============================================================================
346 bool StdMeshers_Regular_1D::computeInternalParameters(const TopoDS_Edge& theEdge,
347 list<double> & theParams,
348 const bool theReverse) const
353 Handle(Geom_Curve) Curve = BRep_Tool::Curve(theEdge, f, l);
354 GeomAdaptor_Curve C3d (Curve, f, l);
356 double length = EdgeLength(theEdge);
364 if ( _hypType == LOCAL_LENGTH )
366 // Local Length hypothesis
367 double nbseg = ceil(length / _value[ BEG_LENGTH_IND ]); // integer sup
369 nbseg = 1; // degenerated edge
370 eltSize = length / nbseg;
374 // Number Of Segments hypothesis
375 int NbSegm = _ivalue[ NB_SEGMENTS_IND ];
376 if ( NbSegm < 1 ) return false;
377 if ( NbSegm == 1 ) return true;
379 switch (_ivalue[ DISTR_TYPE_IND ])
381 case StdMeshers_NumberOfSegments::DT_Scale:
383 double scale = _value[ SCALE_FACTOR_IND ];
385 if (fabs(scale - 1.0) < Precision::Confusion()) {
386 // special case to avoid division on zero
387 for (int i = 1; i < NbSegm; i++) {
388 double param = f + (l - f) * i / NbSegm;
389 theParams.push_back( param );
392 // general case of scale distribution
396 double alpha = pow(scale, 1.0 / (NbSegm - 1));
397 double factor = (l - f) / (1.0 - pow(alpha, NbSegm));
399 for (int i = 1; i < NbSegm; i++) {
400 double param = f + factor * (1.0 - pow(alpha, i));
401 theParams.push_back( param );
407 case StdMeshers_NumberOfSegments::DT_TabFunc:
409 FunctionTable func(_vvalue[ TAB_FUNC_IND ], _ivalue[ CONV_MODE_IND ]);
410 return computeParamByFunc(C3d, f, l, length, theReverse,
411 _ivalue[ NB_SEGMENTS_IND ], func,
415 case StdMeshers_NumberOfSegments::DT_ExprFunc:
417 FunctionExpr func(_svalue[ EXPR_FUNC_IND ].c_str(), _ivalue[ CONV_MODE_IND ]);
418 return computeParamByFunc(C3d, f, l, length, theReverse,
419 _ivalue[ NB_SEGMENTS_IND ], func,
423 case StdMeshers_NumberOfSegments::DT_Regular:
424 eltSize = length / _ivalue[ NB_SEGMENTS_IND ];
430 GCPnts_UniformAbscissa Discret(C3d, eltSize, f, l);
431 if ( !Discret.IsDone() )
434 int NbPoints = Discret.NbPoints();
435 for ( int i = 2; i < NbPoints; i++ )
437 double param = Discret.Parameter(i);
438 theParams.push_back( param );
440 compensateError( eltSize, eltSize, f, l, length, C3d, theParams ); // for PAL9899
444 case BEG_END_LENGTH: {
446 // geometric progression: SUM(n) = ( a1 - an * q ) / ( 1 - q ) = length
448 double a1 = _value[ BEG_LENGTH_IND ];
449 double an = _value[ END_LENGTH_IND ];
450 double q = ( length - a1 ) / ( length - an );
452 double U1 = theReverse ? l : f;
453 double Un = theReverse ? f : l;
455 double eltSize = theReverse ? -a1 : a1;
457 // computes a point on a curve <C3d> at the distance <eltSize>
458 // from the point of parameter <param>.
459 GCPnts_AbscissaPoint Discret( C3d, eltSize, param );
460 if ( !Discret.IsDone() ) break;
461 param = Discret.Parameter();
462 if ( param > f && param < l )
463 theParams.push_back( param );
468 compensateError( a1, an, U1, Un, length, C3d, theParams );
472 case ARITHMETIC_1D: {
474 // arithmetic progression: SUM(n) = ( an - a1 + q ) * ( a1 + an ) / ( 2 * q ) = length
476 double a1 = _value[ BEG_LENGTH_IND ];
477 double an = _value[ END_LENGTH_IND ];
479 double q = ( an - a1 ) / ( 2 *length/( a1 + an ) - 1 );
480 int n = int( 1 + ( an - a1 ) / q );
482 double U1 = theReverse ? l : f;
483 double Un = theReverse ? f : l;
490 while ( n-- > 0 && eltSize * ( Un - U1 ) > 0 ) {
491 // computes a point on a curve <C3d> at the distance <eltSize>
492 // from the point of parameter <param>.
493 GCPnts_AbscissaPoint Discret( C3d, eltSize, param );
494 if ( !Discret.IsDone() ) break;
495 param = Discret.Parameter();
496 if ( param > f && param < l )
497 theParams.push_back( param );
502 compensateError( a1, an, U1, Un, length, C3d, theParams );
509 GCPnts_UniformDeflection Discret(C3d, _value[ DEFLECTION_IND ], f, l, true);
510 if ( !Discret.IsDone() )
513 int NbPoints = Discret.NbPoints();
514 for ( int i = 2; i < NbPoints; i++ )
516 double param = Discret.Parameter(i);
517 theParams.push_back( param );
529 //=============================================================================
533 //=============================================================================
535 bool StdMeshers_Regular_1D::Compute(SMESH_Mesh & aMesh, const TopoDS_Shape & aShape)
537 MESSAGE("StdMeshers_Regular_1D::Compute");
539 if ( _hypType == NONE )
542 SMESHDS_Mesh * meshDS = aMesh.GetMeshDS();
543 aMesh.GetSubMesh(aShape);
545 const TopoDS_Edge & EE = TopoDS::Edge(aShape);
546 TopoDS_Edge E = TopoDS::Edge(EE.Oriented(TopAbs_FORWARD));
547 int shapeID = meshDS->ShapeToIndex( E );
550 Handle(Geom_Curve) Curve = BRep_Tool::Curve(E, f, l);
552 TopoDS_Vertex VFirst, VLast;
553 TopExp::Vertices(E, VFirst, VLast); // Vfirst corresponds to f and Vlast to l
555 ASSERT(!VFirst.IsNull());
556 SMDS_NodeIteratorPtr lid= aMesh.GetSubMesh(VFirst)->GetSubMeshDS()->GetNodes();
559 MESSAGE (" NO NODE BUILT ON VERTEX ");
562 const SMDS_MeshNode * idFirst = lid->next();
564 ASSERT(!VLast.IsNull());
565 lid=aMesh.GetSubMesh(VLast)->GetSubMeshDS()->GetNodes();
567 MESSAGE (" NO NODE BUILT ON VERTEX ");
570 const SMDS_MeshNode * idLast = lid->next();
572 if (!Curve.IsNull()) {
573 list< double > params;
574 bool reversed = false;
575 if ( !_mainEdge.IsNull() )
576 reversed = aMesh.IsReversedInChain( EE, _mainEdge );
578 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
581 if ( ! computeInternalParameters( E, params, reversed )) {
582 //cout << "computeInternalParameters() failed" <<endl;
586 catch ( Standard_Failure ) {
587 //cout << "computeInternalParameters() failed, Standard_Failure" <<endl;
591 // edge extrema (indexes : 1 & NbPoints) already in SMDS (TopoDS_Vertex)
592 // only internal nodes receive an edge position with param on curve
594 const SMDS_MeshNode * idPrev = idFirst;
602 for (list<double>::iterator itU = params.begin(); itU != params.end(); itU++) {
604 gp_Pnt P = Curve->Value(param);
606 //Add the Node in the DataStructure
607 SMDS_MeshNode * node = meshDS->AddNode(P.X(), P.Y(), P.Z());
608 meshDS->SetNodeOnEdge(node, shapeID, param);
611 // create medium node
612 double prm = ( parPrev + param )/2;
613 gp_Pnt PM = Curve->Value(prm);
614 SMDS_MeshNode * NM = meshDS->AddNode(PM.X(), PM.Y(), PM.Z());
615 meshDS->SetNodeOnEdge(NM, shapeID, prm);
616 SMDS_MeshEdge * edge = meshDS->AddEdge(idPrev, node, NM);
617 meshDS->SetMeshElementOnShape(edge, shapeID);
620 SMDS_MeshEdge * edge = meshDS->AddEdge(idPrev, node);
621 meshDS->SetMeshElementOnShape(edge, shapeID);
628 double prm = ( parPrev + parLast )/2;
629 gp_Pnt PM = Curve->Value(prm);
630 SMDS_MeshNode * NM = meshDS->AddNode(PM.X(), PM.Y(), PM.Z());
631 meshDS->SetNodeOnEdge(NM, shapeID, prm);
632 SMDS_MeshEdge * edge = meshDS->AddEdge(idPrev, idLast, NM);
633 meshDS->SetMeshElementOnShape(edge, shapeID);
636 SMDS_MeshEdge* edge = meshDS->AddEdge(idPrev, idLast);
637 meshDS->SetMeshElementOnShape(edge, shapeID);
641 // Edge is a degenerated Edge : We put n = 5 points on the edge.
642 const int NbPoints = 5;
643 BRep_Tool::Range(E, f, l);
644 double du = (l - f) / (NbPoints - 1);
645 //MESSAGE("************* Degenerated edge! *****************");
647 TopoDS_Vertex V1, V2;
648 TopExp::Vertices(E, V1, V2);
649 gp_Pnt P = BRep_Tool::Pnt(V1);
651 const SMDS_MeshNode * idPrev = idFirst;
652 for (int i = 2; i < NbPoints; i++) {
653 double param = f + (i - 1) * du;
654 SMDS_MeshNode * node = meshDS->AddNode(P.X(), P.Y(), P.Z());
656 // create medium node
657 double prm = param - du/2.;
658 SMDS_MeshNode * NM = meshDS->AddNode(P.X(), P.Y(), P.Z());
659 meshDS->SetNodeOnEdge(NM, shapeID, prm);
660 SMDS_MeshEdge * edge = meshDS->AddEdge(idPrev, node, NM);
661 meshDS->SetMeshElementOnShape(edge, shapeID);
664 SMDS_MeshEdge * edge = meshDS->AddEdge(idPrev, node);
665 meshDS->SetMeshElementOnShape(edge, shapeID);
667 meshDS->SetNodeOnEdge(node, shapeID, param);
671 // create medium node
672 double prm = l - du/2.;
673 SMDS_MeshNode * NM = meshDS->AddNode(P.X(), P.Y(), P.Z());
674 meshDS->SetNodeOnEdge(NM, shapeID, prm);
675 SMDS_MeshEdge * edge = meshDS->AddEdge(idPrev, idLast, NM);
676 meshDS->SetMeshElementOnShape(edge, shapeID);
679 SMDS_MeshEdge * edge = meshDS->AddEdge(idPrev, idLast);
680 meshDS->SetMeshElementOnShape(edge, shapeID);
686 //=============================================================================
688 * See comments in SMESH_Algo.cxx
690 //=============================================================================
692 const list <const SMESHDS_Hypothesis *> &
693 StdMeshers_Regular_1D::GetUsedHypothesis(SMESH_Mesh & aMesh,
694 const TopoDS_Shape & aShape,
695 const bool ignoreAuxiliary)
697 _usedHypList.clear();
700 SMESH_HypoFilter auxiliaryFilter, compatibleFilter;
701 auxiliaryFilter.Init( SMESH_HypoFilter::IsAuxiliary() );
702 const bool ignoreAux = true;
703 InitCompatibleHypoFilter( compatibleFilter, ignoreAux );
705 // get non-auxiliary assigned to aShape
706 int nbHyp = aMesh.GetHypotheses( aShape, compatibleFilter, _usedHypList, false );
710 // Check, if propagated from some other edge
711 if (aShape.ShapeType() == TopAbs_EDGE &&
712 aMesh.IsPropagatedHypothesis(aShape, _mainEdge))
714 // Propagation of 1D hypothesis from <aMainEdge> on this edge;
715 // get non-auxiliary assigned to _mainEdge
716 nbHyp = aMesh.GetHypotheses( _mainEdge, compatibleFilter, _usedHypList, true );
720 if (nbHyp == 0) // nothing propagated nor assigned to aShape
722 SMESH_Algo::GetUsedHypothesis( aMesh, aShape, ignoreAuxiliary );
723 nbHyp = _usedHypList.size();
727 // get auxiliary hyps from aShape
728 aMesh.GetHypotheses( aShape, auxiliaryFilter, _usedHypList, true );
730 if ( nbHyp > 1 && ignoreAuxiliary )
731 _usedHypList.clear(); //only one compatible non-auxiliary hypothesis allowed
736 //=============================================================================
740 //=============================================================================
742 ostream & StdMeshers_Regular_1D::SaveTo(ostream & save)
747 //=============================================================================
751 //=============================================================================
753 istream & StdMeshers_Regular_1D::LoadFrom(istream & load)
758 //=============================================================================
762 //=============================================================================
764 ostream & operator <<(ostream & save, StdMeshers_Regular_1D & hyp)
766 return hyp.SaveTo( save );
769 //=============================================================================
773 //=============================================================================
775 istream & operator >>(istream & load, StdMeshers_Regular_1D & hyp)
777 return hyp.LoadFrom( load );