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
30 #include "StdMeshers_Regular_1D.hxx"
31 #include "StdMeshers_Distribution.hxx"
33 #include "StdMeshers_LocalLength.hxx"
34 #include "StdMeshers_NumberOfSegments.hxx"
35 #include "StdMeshers_Arithmetic1D.hxx"
36 #include "StdMeshers_StartEndLength.hxx"
37 #include "StdMeshers_Deflection1D.hxx"
38 #include "StdMeshers_AutomaticLength.hxx"
40 #include "SMESH_Gen.hxx"
41 #include "SMESH_Mesh.hxx"
42 #include "SMESH_HypoFilter.hxx"
43 #include "SMESH_subMesh.hxx"
45 #include "SMDS_MeshElement.hxx"
46 #include "SMDS_MeshNode.hxx"
47 #include "SMDS_EdgePosition.hxx"
49 #include "Utils_SALOME_Exception.hxx"
50 #include "utilities.h"
52 #include <BRep_Tool.hxx>
53 #include <TopoDS_Edge.hxx>
54 #include <TopoDS_Shape.hxx>
55 #include <TopTools_ListIteratorOfListOfShape.hxx>
56 #include <GeomAdaptor_Curve.hxx>
57 #include <GCPnts_AbscissaPoint.hxx>
58 #include <GCPnts_UniformAbscissa.hxx>
59 #include <GCPnts_UniformDeflection.hxx>
60 #include <Precision.hxx>
61 #include <Expr_GeneralExpression.hxx>
62 #include <Expr_NamedUnknown.hxx>
63 #include <Expr_Array1OfNamedUnknown.hxx>
64 #include <ExprIntrp_GenExp.hxx>
65 #include <TColStd_Array1OfReal.hxx>
68 #include <Standard_ErrorHandler.hxx>
69 #include <Standard_Failure.hxx>
76 //=============================================================================
80 //=============================================================================
82 StdMeshers_Regular_1D::StdMeshers_Regular_1D(int hypId, int studyId,
83 SMESH_Gen * gen):SMESH_1D_Algo(hypId, studyId, gen)
85 MESSAGE("StdMeshers_Regular_1D::StdMeshers_Regular_1D");
87 _shapeType = (1 << TopAbs_EDGE);
89 _compatibleHypothesis.push_back("LocalLength");
90 _compatibleHypothesis.push_back("NumberOfSegments");
91 _compatibleHypothesis.push_back("StartEndLength");
92 _compatibleHypothesis.push_back("Deflection1D");
93 _compatibleHypothesis.push_back("Arithmetic1D");
94 _compatibleHypothesis.push_back("AutomaticLength");
96 _compatibleHypothesis.push_back("QuadraticMesh"); // auxiliary !!!
99 //=============================================================================
103 //=============================================================================
105 StdMeshers_Regular_1D::~StdMeshers_Regular_1D()
109 //=============================================================================
113 //=============================================================================
115 bool StdMeshers_Regular_1D::CheckHypothesis
117 const TopoDS_Shape& aShape,
118 SMESH_Hypothesis::Hypothesis_Status& aStatus)
121 _quadraticMesh = false;
123 const bool ignoreAuxiliaryHyps = false;
124 const list <const SMESHDS_Hypothesis * > & hyps =
125 GetUsedHypothesis(aMesh, aShape, ignoreAuxiliaryHyps);
127 // find non-auxiliary hypothesis
128 const SMESHDS_Hypothesis *theHyp = 0;
129 list <const SMESHDS_Hypothesis * >::const_iterator h = hyps.begin();
130 for ( ; h != hyps.end(); ++h ) {
131 if ( static_cast<const SMESH_Hypothesis*>(*h)->IsAuxiliary() ) {
132 if ( strcmp( "QuadraticMesh", (*h)->GetName() ) == 0 )
133 _quadraticMesh = true;
137 theHyp = *h; // use only the first non-auxiliary hypothesis
143 aStatus = SMESH_Hypothesis::HYP_MISSING;
144 return false; // can't work without a hypothesis
147 string hypName = theHyp->GetName();
149 if (hypName == "LocalLength")
151 const StdMeshers_LocalLength * hyp =
152 dynamic_cast <const StdMeshers_LocalLength * >(theHyp);
154 _value[ BEG_LENGTH_IND ] = _value[ END_LENGTH_IND ] = hyp->GetLength();
155 ASSERT( _value[ BEG_LENGTH_IND ] > 0 );
156 _hypType = LOCAL_LENGTH;
157 aStatus = SMESH_Hypothesis::HYP_OK;
160 else if (hypName == "NumberOfSegments")
162 const StdMeshers_NumberOfSegments * hyp =
163 dynamic_cast <const StdMeshers_NumberOfSegments * >(theHyp);
165 _ivalue[ NB_SEGMENTS_IND ] = hyp->GetNumberOfSegments();
166 ASSERT( _ivalue[ NB_SEGMENTS_IND ] > 0 );
167 _ivalue[ DISTR_TYPE_IND ] = (int) hyp->GetDistrType();
168 switch (_ivalue[ DISTR_TYPE_IND ])
170 case StdMeshers_NumberOfSegments::DT_Scale:
171 _value[ SCALE_FACTOR_IND ] = hyp->GetScaleFactor();
173 case StdMeshers_NumberOfSegments::DT_TabFunc:
174 _vvalue[ TAB_FUNC_IND ] = hyp->GetTableFunction();
176 case StdMeshers_NumberOfSegments::DT_ExprFunc:
177 _svalue[ EXPR_FUNC_IND ] = hyp->GetExpressionFunction();
179 case StdMeshers_NumberOfSegments::DT_Regular:
185 if (_ivalue[ DISTR_TYPE_IND ] == StdMeshers_NumberOfSegments::DT_TabFunc ||
186 _ivalue[ DISTR_TYPE_IND ] == StdMeshers_NumberOfSegments::DT_ExprFunc)
187 _ivalue[ CONV_MODE_IND ] = hyp->ConversionMode();
188 _hypType = NB_SEGMENTS;
189 aStatus = SMESH_Hypothesis::HYP_OK;
192 else if (hypName == "Arithmetic1D")
194 const StdMeshers_Arithmetic1D * hyp =
195 dynamic_cast <const StdMeshers_Arithmetic1D * >(theHyp);
197 _value[ BEG_LENGTH_IND ] = hyp->GetLength( true );
198 _value[ END_LENGTH_IND ] = hyp->GetLength( false );
199 ASSERT( _value[ BEG_LENGTH_IND ] > 0 && _value[ END_LENGTH_IND ] > 0 );
200 _hypType = ARITHMETIC_1D;
201 aStatus = SMESH_Hypothesis::HYP_OK;
204 else if (hypName == "StartEndLength")
206 const StdMeshers_StartEndLength * hyp =
207 dynamic_cast <const StdMeshers_StartEndLength * >(theHyp);
209 _value[ BEG_LENGTH_IND ] = hyp->GetLength( true );
210 _value[ END_LENGTH_IND ] = hyp->GetLength( false );
211 ASSERT( _value[ BEG_LENGTH_IND ] > 0 && _value[ END_LENGTH_IND ] > 0 );
212 _hypType = BEG_END_LENGTH;
213 aStatus = SMESH_Hypothesis::HYP_OK;
216 else if (hypName == "Deflection1D")
218 const StdMeshers_Deflection1D * hyp =
219 dynamic_cast <const StdMeshers_Deflection1D * >(theHyp);
221 _value[ DEFLECTION_IND ] = hyp->GetDeflection();
222 ASSERT( _value[ DEFLECTION_IND ] > 0 );
223 _hypType = DEFLECTION;
224 aStatus = SMESH_Hypothesis::HYP_OK;
227 else if (hypName == "AutomaticLength")
229 StdMeshers_AutomaticLength * hyp = const_cast<StdMeshers_AutomaticLength *>
230 (dynamic_cast <const StdMeshers_AutomaticLength * >(theHyp));
232 _value[ BEG_LENGTH_IND ] = _value[ END_LENGTH_IND ] = hyp->GetLength( &aMesh, aShape );
233 ASSERT( _value[ BEG_LENGTH_IND ] > 0 );
234 _hypType = LOCAL_LENGTH;
235 aStatus = SMESH_Hypothesis::HYP_OK;
238 aStatus = SMESH_Hypothesis::HYP_INCOMPATIBLE;
240 return ( _hypType != NONE );
243 //=======================================================================
244 //function : compensateError
245 //purpose : adjust theParams so that the last segment length == an
246 //=======================================================================
248 static void compensateError(double a1, double an,
249 double U1, double Un,
251 GeomAdaptor_Curve& C3d,
252 list<double> & theParams)
254 int i, nPar = theParams.size();
255 if ( a1 + an < length && nPar > 1 )
257 list<double>::reverse_iterator itU = theParams.rbegin();
259 // dist from the last point to the edge end <Un>, it should be equal <an>
260 double Ln = GCPnts_AbscissaPoint::Length( C3d, Ul, Un );
261 double dLn = an - Ln; // error of <an>
262 if ( Abs( dLn ) <= Precision::Confusion() )
264 double dU = Abs( Ul - *itU ); // parametric length of the last but one segment
265 double dUn = dLn * Abs( Un - U1 ) / length; // parametric error of <an>
266 if ( dUn < 0.5 * dU ) { // last segment is a bit shorter than it should
267 dUn = -dUn; // move the last parameter to the edge beginning
269 else { // last segment is much shorter than it should -> remove the last param and
270 theParams.pop_back(); nPar--; // move the rest points toward the edge end
271 Ln = GCPnts_AbscissaPoint::Length( C3d, theParams.back(), Un );
272 dUn = ( an - Ln ) * Abs( Un - U1 ) / length;
273 if ( dUn < 0.5 * dU )
278 double q = dUn / ( nPar - 1 );
279 for ( itU = theParams.rbegin(), i = 1; i < nPar; itU++, i++ ) {
286 static bool computeParamByFunc(Adaptor3d_Curve& C3d, double first, double last,
287 double length, bool theReverse,
288 int nbSeg, Function& func,
289 list<double>& theParams)
292 //OSD::SetSignal( true );
297 MESSAGE( "computeParamByFunc" );
299 int nbPnt = 1 + nbSeg;
300 vector<double> x(nbPnt, 0.);
302 if( !buildDistribution( func, 0.0, 1.0, nbSeg, x, 1E-4 ) )
305 MESSAGE( "Points:\n" );
307 for( int i=0; i<=nbSeg; i++ )
309 sprintf( buf, "%f\n", float(x[i] ) );
315 // apply parameters in range [0,1] to the space of the curve
316 double prevU = first;
323 for( int i = 1; i < nbSeg; i++ )
325 double curvLength = length * (x[i] - x[i-1]) * sign;
326 GCPnts_AbscissaPoint Discret( C3d, curvLength, prevU );
327 if ( !Discret.IsDone() )
329 double U = Discret.Parameter();
330 if ( U > first && U < last )
331 theParams.push_back( U );
339 //=============================================================================
343 //=============================================================================
344 bool StdMeshers_Regular_1D::computeInternalParameters(const TopoDS_Edge& theEdge,
345 list<double> & theParams,
346 const bool theReverse) const
351 Handle(Geom_Curve) Curve = BRep_Tool::Curve(theEdge, f, l);
352 GeomAdaptor_Curve C3d (Curve, f, l);
354 double length = EdgeLength(theEdge);
362 if ( _hypType == LOCAL_LENGTH )
364 // Local Length hypothesis
365 double nbseg = ceil(length / _value[ BEG_LENGTH_IND ]); // integer sup
367 nbseg = 1; // degenerated edge
368 eltSize = length / nbseg;
372 // Number Of Segments hypothesis
373 int NbSegm = _ivalue[ NB_SEGMENTS_IND ];
374 if ( NbSegm < 1 ) return false;
375 if ( NbSegm == 1 ) return true;
377 switch (_ivalue[ DISTR_TYPE_IND ])
379 case StdMeshers_NumberOfSegments::DT_Scale:
381 double scale = _value[ SCALE_FACTOR_IND ];
383 if (fabs(scale - 1.0) < Precision::Confusion()) {
384 // special case to avoid division on zero
385 for (int i = 1; i < NbSegm; i++) {
386 double param = f + (l - f) * i / NbSegm;
387 theParams.push_back( param );
390 // general case of scale distribution
394 double alpha = pow(scale, 1.0 / (NbSegm - 1));
395 double factor = (l - f) / (1.0 - pow(alpha, NbSegm));
397 for (int i = 1; i < NbSegm; i++) {
398 double param = f + factor * (1.0 - pow(alpha, i));
399 theParams.push_back( param );
405 case StdMeshers_NumberOfSegments::DT_TabFunc:
407 FunctionTable func(_vvalue[ TAB_FUNC_IND ], _ivalue[ CONV_MODE_IND ]);
408 return computeParamByFunc(C3d, f, l, length, theReverse,
409 _ivalue[ NB_SEGMENTS_IND ], func,
413 case StdMeshers_NumberOfSegments::DT_ExprFunc:
415 FunctionExpr func(_svalue[ EXPR_FUNC_IND ].c_str(), _ivalue[ CONV_MODE_IND ]);
416 return computeParamByFunc(C3d, f, l, length, theReverse,
417 _ivalue[ NB_SEGMENTS_IND ], func,
421 case StdMeshers_NumberOfSegments::DT_Regular:
422 eltSize = length / _ivalue[ NB_SEGMENTS_IND ];
428 GCPnts_UniformAbscissa Discret(C3d, eltSize, f, l);
429 if ( !Discret.IsDone() )
432 int NbPoints = Discret.NbPoints();
433 for ( int i = 2; i < NbPoints; i++ )
435 double param = Discret.Parameter(i);
436 theParams.push_back( param );
438 compensateError( eltSize, eltSize, f, l, length, C3d, theParams ); // for PAL9899
442 case BEG_END_LENGTH: {
444 // geometric progression: SUM(n) = ( a1 - an * q ) / ( 1 - q ) = length
446 double a1 = _value[ BEG_LENGTH_IND ];
447 double an = _value[ END_LENGTH_IND ];
448 double q = ( length - a1 ) / ( length - an );
450 double U1 = theReverse ? l : f;
451 double Un = theReverse ? f : l;
453 double eltSize = theReverse ? -a1 : a1;
455 // computes a point on a curve <C3d> at the distance <eltSize>
456 // from the point of parameter <param>.
457 GCPnts_AbscissaPoint Discret( C3d, eltSize, param );
458 if ( !Discret.IsDone() ) break;
459 param = Discret.Parameter();
460 if ( param > f && param < l )
461 theParams.push_back( param );
466 compensateError( a1, an, U1, Un, length, C3d, theParams );
470 case ARITHMETIC_1D: {
472 // arithmetic progression: SUM(n) = ( an - a1 + q ) * ( a1 + an ) / ( 2 * q ) = length
474 double a1 = _value[ BEG_LENGTH_IND ];
475 double an = _value[ END_LENGTH_IND ];
477 double q = ( an - a1 ) / ( 2 *length/( a1 + an ) - 1 );
478 int n = int( 1 + ( an - a1 ) / q );
480 double U1 = theReverse ? l : f;
481 double Un = theReverse ? f : l;
488 while ( n-- > 0 && eltSize * ( Un - U1 ) > 0 ) {
489 // computes a point on a curve <C3d> at the distance <eltSize>
490 // from the point of parameter <param>.
491 GCPnts_AbscissaPoint Discret( C3d, eltSize, param );
492 if ( !Discret.IsDone() ) break;
493 param = Discret.Parameter();
494 if ( param > f && param < l )
495 theParams.push_back( param );
500 compensateError( a1, an, U1, Un, length, C3d, theParams );
507 GCPnts_UniformDeflection Discret(C3d, _value[ DEFLECTION_IND ], f, l, true);
508 if ( !Discret.IsDone() )
511 int NbPoints = Discret.NbPoints();
512 for ( int i = 2; i < NbPoints; i++ )
514 double param = Discret.Parameter(i);
515 theParams.push_back( param );
527 //=============================================================================
531 //=============================================================================
533 bool StdMeshers_Regular_1D::Compute(SMESH_Mesh & aMesh, const TopoDS_Shape & aShape)
535 MESSAGE("StdMeshers_Regular_1D::Compute");
537 if ( _hypType == NONE )
540 SMESHDS_Mesh * meshDS = aMesh.GetMeshDS();
541 aMesh.GetSubMesh(aShape);
543 const TopoDS_Edge & EE = TopoDS::Edge(aShape);
544 TopoDS_Edge E = TopoDS::Edge(EE.Oriented(TopAbs_FORWARD));
545 int shapeID = meshDS->ShapeToIndex( E );
548 Handle(Geom_Curve) Curve = BRep_Tool::Curve(E, f, l);
550 TopoDS_Vertex VFirst, VLast;
551 TopExp::Vertices(E, VFirst, VLast); // Vfirst corresponds to f and Vlast to l
553 ASSERT(!VFirst.IsNull());
554 SMDS_NodeIteratorPtr lid= aMesh.GetSubMesh(VFirst)->GetSubMeshDS()->GetNodes();
557 MESSAGE (" NO NODE BUILT ON VERTEX ");
560 const SMDS_MeshNode * idFirst = lid->next();
562 ASSERT(!VLast.IsNull());
563 lid=aMesh.GetSubMesh(VLast)->GetSubMeshDS()->GetNodes();
565 MESSAGE (" NO NODE BUILT ON VERTEX ");
568 const SMDS_MeshNode * idLast = lid->next();
570 if (!Curve.IsNull()) {
571 list< double > params;
572 bool reversed = false;
573 if ( !_mainEdge.IsNull() )
574 reversed = aMesh.IsReversedInChain( EE, _mainEdge );
576 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
579 if ( ! computeInternalParameters( E, params, reversed )) {
580 //cout << "computeInternalParameters() failed" <<endl;
584 catch ( Standard_Failure ) {
585 //cout << "computeInternalParameters() failed, Standard_Failure" <<endl;
589 // edge extrema (indexes : 1 & NbPoints) already in SMDS (TopoDS_Vertex)
590 // only internal nodes receive an edge position with param on curve
592 const SMDS_MeshNode * idPrev = idFirst;
600 for (list<double>::iterator itU = params.begin(); itU != params.end(); itU++) {
602 gp_Pnt P = Curve->Value(param);
604 //Add the Node in the DataStructure
605 SMDS_MeshNode * node = meshDS->AddNode(P.X(), P.Y(), P.Z());
606 meshDS->SetNodeOnEdge(node, shapeID, param);
609 // create medium node
610 double prm = ( parPrev + param )/2;
611 gp_Pnt PM = Curve->Value(prm);
612 SMDS_MeshNode * NM = meshDS->AddNode(PM.X(), PM.Y(), PM.Z());
613 meshDS->SetNodeOnEdge(NM, shapeID, prm);
614 SMDS_MeshEdge * edge = meshDS->AddEdge(idPrev, node, NM);
615 meshDS->SetMeshElementOnShape(edge, shapeID);
618 SMDS_MeshEdge * edge = meshDS->AddEdge(idPrev, node);
619 meshDS->SetMeshElementOnShape(edge, shapeID);
626 double prm = ( parPrev + parLast )/2;
627 gp_Pnt PM = Curve->Value(prm);
628 SMDS_MeshNode * NM = meshDS->AddNode(PM.X(), PM.Y(), PM.Z());
629 meshDS->SetNodeOnEdge(NM, shapeID, prm);
630 SMDS_MeshEdge * edge = meshDS->AddEdge(idPrev, idLast, NM);
631 meshDS->SetMeshElementOnShape(edge, shapeID);
634 SMDS_MeshEdge* edge = meshDS->AddEdge(idPrev, idLast);
635 meshDS->SetMeshElementOnShape(edge, shapeID);
639 // Edge is a degenerated Edge : We put n = 5 points on the edge.
640 const int NbPoints = 5;
641 BRep_Tool::Range(E, f, l);
642 double du = (l - f) / (NbPoints - 1);
643 //MESSAGE("************* Degenerated edge! *****************");
645 TopoDS_Vertex V1, V2;
646 TopExp::Vertices(E, V1, V2);
647 gp_Pnt P = BRep_Tool::Pnt(V1);
649 const SMDS_MeshNode * idPrev = idFirst;
650 for (int i = 2; i < NbPoints; i++) {
651 double param = f + (i - 1) * du;
652 SMDS_MeshNode * node = meshDS->AddNode(P.X(), P.Y(), P.Z());
654 // create medium node
655 double prm = param - du/2.;
656 SMDS_MeshNode * NM = meshDS->AddNode(P.X(), P.Y(), P.Z());
657 meshDS->SetNodeOnEdge(NM, shapeID, prm);
658 SMDS_MeshEdge * edge = meshDS->AddEdge(idPrev, node, NM);
659 meshDS->SetMeshElementOnShape(edge, shapeID);
662 SMDS_MeshEdge * edge = meshDS->AddEdge(idPrev, node);
663 meshDS->SetMeshElementOnShape(edge, shapeID);
665 meshDS->SetNodeOnEdge(node, shapeID, param);
669 // create medium node
670 double prm = l - du/2.;
671 SMDS_MeshNode * NM = meshDS->AddNode(P.X(), P.Y(), P.Z());
672 meshDS->SetNodeOnEdge(NM, shapeID, prm);
673 SMDS_MeshEdge * edge = meshDS->AddEdge(idPrev, idLast, NM);
674 meshDS->SetMeshElementOnShape(edge, shapeID);
677 SMDS_MeshEdge * edge = meshDS->AddEdge(idPrev, idLast);
678 meshDS->SetMeshElementOnShape(edge, shapeID);
684 //=============================================================================
686 * See comments in SMESH_Algo.cxx
688 //=============================================================================
690 const list <const SMESHDS_Hypothesis *> &
691 StdMeshers_Regular_1D::GetUsedHypothesis(SMESH_Mesh & aMesh,
692 const TopoDS_Shape & aShape,
693 const bool ignoreAuxiliary)
695 _usedHypList.clear();
698 SMESH_HypoFilter auxiliaryFilter, compatibleFilter;
699 auxiliaryFilter.Init( SMESH_HypoFilter::IsAuxiliary() );
700 const bool ignoreAux = true;
701 InitCompatibleHypoFilter( compatibleFilter, ignoreAux );
703 // get non-auxiliary assigned to aShape
704 int nbHyp = aMesh.GetHypotheses( aShape, compatibleFilter, _usedHypList, false );
708 // Check, if propagated from some other edge
709 if (aShape.ShapeType() == TopAbs_EDGE &&
710 aMesh.IsPropagatedHypothesis(aShape, _mainEdge))
712 // Propagation of 1D hypothesis from <aMainEdge> on this edge;
713 // get non-auxiliary assigned to _mainEdge
714 nbHyp = aMesh.GetHypotheses( _mainEdge, compatibleFilter, _usedHypList, true );
718 if (nbHyp == 0) // nothing propagated nor assigned to aShape
720 SMESH_Algo::GetUsedHypothesis( aMesh, aShape, ignoreAuxiliary );
721 nbHyp = _usedHypList.size();
725 // get auxiliary hyps from aShape
726 aMesh.GetHypotheses( aShape, auxiliaryFilter, _usedHypList, true );
728 if ( nbHyp > 1 && ignoreAuxiliary )
729 _usedHypList.clear(); //only one compatible non-auxiliary hypothesis allowed
734 //=============================================================================
738 //=============================================================================
740 ostream & StdMeshers_Regular_1D::SaveTo(ostream & save)
745 //=============================================================================
749 //=============================================================================
751 istream & StdMeshers_Regular_1D::LoadFrom(istream & load)
756 //=============================================================================
760 //=============================================================================
762 ostream & operator <<(ostream & save, StdMeshers_Regular_1D & hyp)
764 return hyp.SaveTo( save );
767 //=============================================================================
771 //=============================================================================
773 istream & operator >>(istream & load, StdMeshers_Regular_1D & hyp)
775 return hyp.LoadFrom( load );