1 // File : FrontTrack_Projector.cxx
2 // Created : Wed Apr 26 20:33:55 2017
3 // Author : Edward AGAPOV (eap)
5 #include "FrontTrack_Projector.hxx"
7 #include <BRepAdaptor_Curve.hxx>
8 #include <BRepBndLib.hxx>
9 #include <BRepTopAdaptor_FClass2d.hxx>
10 #include <BRep_Tool.hxx>
13 #include <GCPnts_UniformDeflection.hxx>
14 #include <GeomAdaptor_Curve.hxx>
15 #include <GeomLib_IsPlanarSurface.hxx>
16 #include <ShapeAnalysis_Curve.hxx>
17 #include <ShapeAnalysis_Surface.hxx>
20 #include <TopoDS_Edge.hxx>
21 #include <TopoDS_Face.hxx>
22 #include <TopoDS_Vertex.hxx>
23 #include <gp_Circ.hxx>
24 #include <gp_Cylinder.hxx>
28 #include <gp_Sphere.hxx>
33 //-----------------------------------------------------------------------------
35 * \brief Root class of a projector of a point to a boundary shape
37 struct FT_RealProjector
39 virtual ~FT_RealProjector() {}
42 * \brief Project a point to a boundary shape
43 * \param [in] point - the point to project
44 * \param [out] newSolution - position on the shape (U or UV) found during the projection
45 * \param [in] prevSolution - position already found during the projection of a neighbor point
46 * \return gp_Pnt - the projection point
48 virtual gp_Pnt project( const gp_Pnt& point,
50 const double* prevSolution = 0) = 0;
53 * \brief Project a point to a boundary shape and check if the projection is within
55 * \param [in] point - the point to project
56 * \param [in] maxDist2 - the maximal allowed square distance between point and projection
57 * \param [out] projection - the projection point
58 * \param [out] newSolution - position on the shape (U or UV) found during the projection
59 * \param [in] prevSolution - position already found during the projection of a neighbor point
60 * \return bool - false if the projection point lies out of the shape boundary or
61 the distance the point and the projection is more than sqrt(maxDist2)
63 virtual bool projectAndClassify( const gp_Pnt& point,
64 const double maxDist2,
67 const double* prevSolution = 0) = 0;
69 // return true if a previously found solution can be used to speed up the projection
71 virtual bool canUsePrevSolution() const { return false; }
74 double _dist; // distance between the point being projected and its projection
77 namespace // actual projection algorithms
79 const double theEPS = 1e-12;
81 //================================================================================
83 * \brief Projector to any curve
85 //================================================================================
87 struct CurveProjector : public FT_RealProjector
89 BRepAdaptor_Curve _curve;
91 ShapeAnalysis_Curve _projector;
94 //-----------------------------------------------------------------------------
95 CurveProjector( const TopoDS_Edge& e, const double tol ):
96 _curve( e ), _tol( tol )
98 BRep_Tool::Range( e, _uRange[0], _uRange[1] );
101 //-----------------------------------------------------------------------------
102 // project a point to the curve
103 virtual gp_Pnt project( const gp_Pnt& P,
105 const double* prevSolution = 0)
112 _dist = _projector.NextProject( prevSolution[0], _curve, P, _tol, proj, param );
116 _dist = _projector.Project( _curve, P, _tol, proj, param, false );
118 proj = _curve.Value( param );
120 newSolution[0] = param;
125 //-----------------------------------------------------------------------------
126 // project a point to a curve and check if the projection is within the curve boundary
127 virtual bool projectAndClassify( const gp_Pnt& point,
128 const double maxDist2,
131 const double* prevSolution = 0)
133 projection = project( point, newSolution, prevSolution );
134 return ( _uRange[0] < newSolution[0] && newSolution[0] < _uRange[1] &&
135 _dist * _dist < maxDist2 );
138 //-----------------------------------------------------------------------------
139 // return true if a previously found solution can be used to speed up the projection
140 virtual bool canUsePrevSolution() const { return true; }
143 //================================================================================
145 * \brief Projector to a straight curve. Don't project, classify only
147 //================================================================================
149 struct LineProjector : public FT_RealProjector
153 //-----------------------------------------------------------------------------
154 LineProjector( TopoDS_Edge e )
156 e.Orientation( TopAbs_FORWARD );
157 _p0 = BRep_Tool::Pnt( TopExp::FirstVertex( e ));
158 _p1 = BRep_Tool::Pnt( TopExp::LastVertex ( e ));
161 //-----------------------------------------------------------------------------
163 virtual gp_Pnt project( const gp_Pnt& P,
165 const double* prevSolution = 0)
169 //-----------------------------------------------------------------------------
170 // check if a point lies within the line segment
171 virtual bool projectAndClassify( const gp_Pnt& point,
172 const double maxDist2,
175 const double* prevSolution = 0)
177 gp_Vec edge( _p0, _p1 );
178 gp_Vec p0p ( _p0, point );
179 double u = ( edge * p0p ) / edge.SquareMagnitude(); // param [0,1] on the edge
180 projection = ( 1. - u ) * _p0.XYZ() + u * _p1.XYZ(); // projection of the point on the edge
181 if ( u < 0 || 1 < u )
185 return point.SquareDistance( projection ) < theEPS * theEPS;
189 //================================================================================
191 * \brief Projector to a circular edge
193 //================================================================================
195 struct CircleProjector : public FT_RealProjector
200 //-----------------------------------------------------------------------------
201 CircleProjector( const gp_Circ& c, const double f, const double l ):
208 //-----------------------------------------------------------------------------
209 // project a point to the circle
210 virtual gp_Pnt project( const gp_Pnt& P,
212 const double* prevSolution = 0)
214 // assume that P is already on the the plane of circle, since
215 // it is in the middle of two points lying on the circle
217 // move P to the circle
218 const gp_Pnt& O = _circle.Location();
219 gp_Vec radiusVec( O, P );
220 double radius = radiusVec.Magnitude();
221 if ( radius < std::numeric_limits<double>::min() )
222 return P; // P in on the axe
224 gp_Pnt proj = O.Translated( radiusVec.Multiplied( _circle.Radius() / radius ));
226 _dist = _circle.Radius() - radius;
231 //-----------------------------------------------------------------------------
232 // project and check if a projection lies within the circular edge
233 virtual bool projectAndClassify( const gp_Pnt& point,
234 const double maxDist2,
237 const double* prevSolution = 0)
240 projection = project( point, newSolution );
241 if ( _dist < 0 || // ?
242 _dist * _dist > maxDist2 )
245 newSolution[0] = ElCLib::Parameter( _circle, projection );
246 return ( _uRange[0] < newSolution[0] && newSolution[0] < _uRange[1] );
250 //================================================================================
252 * \brief Projector to any surface
254 //================================================================================
256 struct SurfaceProjector : public FT_RealProjector
258 ShapeAnalysis_Surface _projector;
260 BRepTopAdaptor_FClass2d* _classifier;
262 //-----------------------------------------------------------------------------
263 SurfaceProjector( const TopoDS_Face& face, const double tol, BRepTopAdaptor_FClass2d* cls ):
264 _projector( BRep_Tool::Surface( face )),
269 //-----------------------------------------------------------------------------
270 // delete _classifier
276 //-----------------------------------------------------------------------------
277 // project a point to a surface
278 virtual gp_Pnt project( const gp_Pnt& P,
280 const double* prevSolution = 0)
286 gp_Pnt2d prevUV( prevSolution[0], prevSolution[1] );
287 uv = _projector.NextValueOfUV( prevUV, P, _tol );
291 uv = _projector.ValueOfUV( P, _tol );
294 uv.Coord( newSolution[0], newSolution[1] );
296 gp_Pnt proj = _projector.Value( uv );
298 _dist = _projector.Gap();
303 //-----------------------------------------------------------------------------
304 // project a point to a surface and check if the projection is within the surface boundary
305 virtual bool projectAndClassify( const gp_Pnt& point,
306 const double maxDist2,
309 const double* prevSolution = 0)
311 projection = project( point, newSolution, prevSolution );
312 return ( _dist * _dist < maxDist2 ) && classify( newSolution );
315 //-----------------------------------------------------------------------------
316 // check if the projection is within the shape boundary
317 bool classify( const double* newSolution )
319 TopAbs_State state = _classifier->Perform( gp_Pnt2d( newSolution[0], newSolution[1]) );
320 return ( state != TopAbs_OUT );
323 //-----------------------------------------------------------------------------
324 // return true if a previously found solution can be used to speed up the projection
325 virtual bool canUsePrevSolution() const { return true; }
328 //================================================================================
330 * \brief Projector to a plane. Don't project, classify only
332 //================================================================================
334 struct PlaneProjector : public SurfaceProjector
337 bool _isRealPlane; // false means that a surface is planar but parametrization is different
339 //-----------------------------------------------------------------------------
340 PlaneProjector( const gp_Pln& pln,
341 const TopoDS_Face& face,
342 BRepTopAdaptor_FClass2d* cls,
343 bool isRealPlane=true):
344 SurfaceProjector( face, 0, cls ),
346 _isRealPlane( isRealPlane )
349 //-----------------------------------------------------------------------------
351 virtual gp_Pnt project( const gp_Pnt& P,
353 const double* prevSolution = 0)
357 //-----------------------------------------------------------------------------
358 // check if a point lies within the boundry of the planar face
359 virtual bool projectAndClassify( const gp_Pnt& point,
360 const double maxDist2,
363 const double* prevSolution = 0)
367 ElSLib::PlaneParameters( _plane.Position(), point, newSolution[0], newSolution[1]);
368 projection = ElSLib::PlaneValue ( newSolution[0], newSolution[1], _plane.Position() );
369 if ( projection.SquareDistance( point ) > theEPS * theEPS )
372 return SurfaceProjector::classify( newSolution );
376 return SurfaceProjector::projectAndClassify( point, maxDist2, projection,
377 newSolution, prevSolution );
380 //-----------------------------------------------------------------------------
381 // return true if a previously found solution can be used to speed up the projection
382 virtual bool canUsePrevSolution() const { return false; }
385 //================================================================================
387 * \brief Projector to a cylinder
389 //================================================================================
391 struct CylinderProjector : public SurfaceProjector
393 gp_Cylinder _cylinder;
395 //-----------------------------------------------------------------------------
396 CylinderProjector( const gp_Cylinder& c,
397 const TopoDS_Face& face,
398 BRepTopAdaptor_FClass2d* cls ):
399 SurfaceProjector( face, 0, cls ),
403 //-----------------------------------------------------------------------------
404 // project a point to the cylinder
405 virtual gp_Pnt project( const gp_Pnt& P,
407 const double* prevSolution = 0)
409 // project the point P to the cylinder axis -> Pp
410 const gp_Pnt& O = _cylinder.Position().Location();
411 const gp_Dir& axe = _cylinder.Position().Direction();
412 gp_Vec trsl = gp_Vec( axe ).Multiplied( gp_Vec( O, P ).Dot( axe ));
413 gp_Pnt Pp = O.Translated( trsl );
415 // move Pp to the cylinder
416 gp_Vec radiusVec( Pp, P );
417 double radius = radiusVec.Magnitude();
418 if ( radius < std::numeric_limits<double>::min() )
419 return P; // P in on the axe
421 gp_Pnt proj = Pp.Translated( radiusVec.Multiplied( _cylinder.Radius() / radius ));
423 _dist = _cylinder.Radius() - radius;
427 //-----------------------------------------------------------------------------
428 // project a point to the cylinder and check if the projection is within the surface boundary
429 virtual bool projectAndClassify( const gp_Pnt& point,
430 const double maxDist2,
433 const double* prevSolution = 0)
435 ElSLib::CylinderParameters( _cylinder.Position(), _cylinder.Radius(), point,
436 newSolution[0], newSolution[1]);
437 projection = ElSLib::CylinderValue( newSolution[0], newSolution[1],
438 _cylinder.Position(), _cylinder.Radius() );
440 return ( _dist * _dist < maxDist2 ) && SurfaceProjector::classify( newSolution );
442 //-----------------------------------------------------------------------------
443 // return true if a previously found solution can be used to speed up the projection
444 virtual bool canUsePrevSolution() const { return false; }
447 //================================================================================
449 * \brief Projector to a cone
451 //================================================================================
453 struct ConeProjector : public SurfaceProjector
457 //-----------------------------------------------------------------------------
458 ConeProjector( const gp_Cone& c,
459 const TopoDS_Face& face,
460 BRepTopAdaptor_FClass2d* cls ):
461 SurfaceProjector( face, 0, cls ),
465 //-----------------------------------------------------------------------------
466 // project a point to the cone
467 virtual gp_Pnt project( const gp_Pnt& point,
469 const double* prevSolution = 0)
471 ElSLib::ConeParameters( _cone.Position(), _cone.RefRadius(), _cone.SemiAngle(),
472 point, newSolution[0], newSolution[1]);
473 gp_Pnt proj = ElSLib::ConeValue( newSolution[0], newSolution[1],
474 _cone.Position(), _cone.RefRadius(), _cone.SemiAngle() );
475 _dist = point.Distance( proj );
480 //-----------------------------------------------------------------------------
481 // project a point to the cone and check if the projection is within the surface boundary
482 virtual bool projectAndClassify( const gp_Pnt& point,
483 const double maxDist2,
486 const double* prevSolution = 0)
488 projection = project( point, newSolution, prevSolution );
490 return ( _dist * _dist < maxDist2 ) && SurfaceProjector::classify( newSolution );
492 //-----------------------------------------------------------------------------
493 // return true if a previously found solution can be used to speed up the projection
494 virtual bool canUsePrevSolution() const { return false; }
497 //================================================================================
499 * \brief Projector to a sphere
501 //================================================================================
503 struct SphereProjector : public SurfaceProjector
507 //-----------------------------------------------------------------------------
508 SphereProjector( const gp_Sphere& s,
509 const TopoDS_Face& face,
510 BRepTopAdaptor_FClass2d* cls ):
511 SurfaceProjector( face, 0, cls ),
515 //-----------------------------------------------------------------------------
516 // project a point to the sphere
517 virtual gp_Pnt project( const gp_Pnt& P,
519 const double* prevSolution = 0)
521 // move Pp to the Sphere
522 const gp_Pnt& O = _sphere.Location();
523 gp_Vec radiusVec( O, P );
524 double radius = radiusVec.Magnitude();
525 if ( radius < std::numeric_limits<double>::min() )
526 return P; // P is on O
528 gp_Pnt proj = O.Translated( radiusVec.Multiplied( _sphere.Radius() / radius ));
530 _dist = _sphere.Radius() - radius;
535 //-----------------------------------------------------------------------------
536 // project a point to the sphere and check if the projection is within the surface boundary
537 virtual bool projectAndClassify( const gp_Pnt& point,
538 const double maxDist2,
541 const double* prevSolution = 0)
543 ElSLib::SphereParameters( _sphere.Position(), _sphere.Radius(), point,
544 newSolution[0], newSolution[1]);
545 projection = ElSLib::SphereValue( newSolution[0], newSolution[1],
546 _sphere.Position(), _sphere.Radius() );
548 return ( _dist * _dist < maxDist2 ) && SurfaceProjector::classify( newSolution );
550 //-----------------------------------------------------------------------------
551 // return true if a previously found solution can be used to speed up the projection
552 virtual bool canUsePrevSolution() const { return false; }
555 //================================================================================
557 * \brief Projector to a torus
559 //================================================================================
561 struct TorusProjector : public SurfaceProjector
565 //-----------------------------------------------------------------------------
566 TorusProjector( const gp_Torus& t,
567 const TopoDS_Face& face,
568 BRepTopAdaptor_FClass2d* cls ):
569 SurfaceProjector( face, 0, cls ),
573 //-----------------------------------------------------------------------------
574 // project a point to the torus
575 virtual gp_Pnt project( const gp_Pnt& point,
577 const double* prevSolution = 0)
579 ElSLib::TorusParameters( _torus.Position(), _torus.MajorRadius(), _torus.MinorRadius(),
580 point, newSolution[0], newSolution[1]);
581 gp_Pnt proj = ElSLib::TorusValue( newSolution[0], newSolution[1],
582 _torus.Position(), _torus.MajorRadius(), _torus.MinorRadius() );
583 _dist = point.Distance( proj );
588 //-----------------------------------------------------------------------------
589 // project a point to the torus and check if the projection is within the surface boundary
590 virtual bool projectAndClassify( const gp_Pnt& point,
591 const double maxDist2,
594 const double* prevSolution = 0)
596 projection = project( point, newSolution, prevSolution );
598 return ( _dist * _dist < maxDist2 ) && SurfaceProjector::classify( newSolution );
600 //-----------------------------------------------------------------------------
601 // return true if a previously found solution can be used to speed up the projection
602 virtual bool canUsePrevSolution() const { return false; }
605 //================================================================================
607 * \brief Check if a curve can be considered straight
609 //================================================================================
611 bool isStraight( const GeomAdaptor_Curve& curve, const double tol )
613 // rough check: evaluate how far from a straight line connecting the curve ends
614 // stand several internal points of the curve
616 const double f = curve.FirstParameter();
617 const double l = curve.LastParameter();
618 const gp_Pnt pf = curve.Value( f );
619 const gp_Pnt pl = curve.Value( l );
620 const gp_Vec lineVec( pf, pl );
621 const double lineLen2 = lineVec.SquareMagnitude();
622 if ( lineLen2 < std::numeric_limits< double >::min() )
623 return false; // E seems closed
625 const double nbSamples = 7;
626 for ( int i = 0; i < nbSamples; ++i )
628 const double r = ( i + 1 ) / nbSamples;
629 const gp_Pnt pi = curve.Value( f * r + l * ( 1 - r ));
630 const gp_Vec vi( pf, pi );
631 const double h2 = lineVec.Crossed( vi ).SquareMagnitude() / lineLen2;
632 if ( h2 > tol * tol )
637 GCPnts_UniformDeflection divider( curve, tol );
638 return ( divider.IsDone() && divider.NbPoints() < 3 );
642 //================================================================================
644 * \brief Initialize with a boundary shape
646 //================================================================================
648 FT_Projector::FT_Projector(const TopoDS_Shape& shape)
651 setBoundaryShape( shape );
654 //================================================================================
656 * \brief Copy another projector
658 //================================================================================
660 FT_Projector::FT_Projector(const FT_Projector& other)
663 _shape = other._shape;
664 _bndBox = other._bndBox;
667 //================================================================================
669 * \brief Destructor. Delete _realProjector
671 //================================================================================
673 FT_Projector::~FT_Projector()
675 delete _realProjector;
678 //================================================================================
680 * \brief Initialize with a boundary shape. Compute the bounding box
682 //================================================================================
684 void FT_Projector::setBoundaryShape(const TopoDS_Shape& shape)
686 delete _realProjector; _realProjector = 0;
688 if ( shape.IsNull() )
691 BRepBndLib::Add( shape, _bndBox );
692 _bndBox.Enlarge( 1e-5 * sqrt( _bndBox.SquareExtent() ));
695 //================================================================================
697 * \brief Create a real projector
699 //================================================================================
701 void FT_Projector::prepareForProjection()
703 if ( _shape.IsNull() || _realProjector )
706 if ( _shape.ShapeType() == TopAbs_EDGE )
708 const TopoDS_Edge& edge = TopoDS::Edge( _shape );
710 double tol = 1e-6 * sqrt( _bndBox.SquareExtent() );
713 Handle(Geom_Curve) curve = BRep_Tool::Curve( edge, f,l );
714 if ( curve.IsNull() )
715 return; // degenerated edge
717 GeomAdaptor_Curve acurve( curve, f, l );
718 switch ( acurve.GetType() )
721 _realProjector = new LineProjector( edge );
724 _realProjector = new CircleProjector( acurve.Circle(), f, l );
726 case GeomAbs_BezierCurve:
727 case GeomAbs_BSplineCurve:
728 case GeomAbs_OffsetCurve:
729 case GeomAbs_OtherCurve:
730 if ( isStraight( acurve, tol ))
732 _realProjector = new LineProjector( edge );
735 case GeomAbs_Ellipse:
736 case GeomAbs_Hyperbola:
737 case GeomAbs_Parabola:
738 _realProjector = new CurveProjector( edge, tol );
741 else if ( _shape.ShapeType() == TopAbs_FACE )
743 TopoDS_Face face = TopoDS::Face( _shape );
745 Handle(Geom_Surface) surface = BRep_Tool::Surface( face );
746 if ( surface.IsNull() )
749 GeomAdaptor_Surface asurface( surface );
750 Standard_Real tol = BRep_Tool::Tolerance( face );
751 Standard_Real toluv = Min( asurface.UResolution( tol ), asurface.VResolution( tol ));
752 BRepTopAdaptor_FClass2d* classifier = new BRepTopAdaptor_FClass2d( face, toluv );
754 switch ( asurface.GetType() )
757 _realProjector = new PlaneProjector( asurface.Plane(), face, classifier );
759 case GeomAbs_Cylinder:
760 _realProjector = new CylinderProjector( asurface.Cylinder(), face, classifier );
763 _realProjector = new SphereProjector( asurface.Sphere(), face, classifier );
766 _realProjector = new ConeProjector( asurface.Cone(), face, classifier );
769 _realProjector = new TorusProjector( asurface.Torus(), face, classifier );
771 case GeomAbs_BezierSurface:
772 case GeomAbs_BSplineSurface:
773 case GeomAbs_SurfaceOfRevolution:
774 case GeomAbs_SurfaceOfExtrusion:
775 case GeomAbs_OffsetSurface:
776 case GeomAbs_OtherSurface:
777 GeomLib_IsPlanarSurface isPlaneCheck( surface, tol );
778 if ( isPlaneCheck.IsPlanar() )
780 _realProjector = new PlaneProjector( isPlaneCheck.Plan(), face, classifier,
781 /*isRealPlane=*/false);
785 _realProjector = new SurfaceProjector( face, tol, classifier );
792 //================================================================================
794 * \brief Return true if projection is not needed
796 //================================================================================
798 bool FT_Projector::isPlanarBoundary() const
800 return ( dynamic_cast< LineProjector* >( _realProjector ) ||
801 dynamic_cast< PlaneProjector* >( _realProjector ) );
804 //================================================================================
806 * \brief Check if a point lies on the boundary shape
807 * \param [in] point - the point to check
808 * \param [in] tol2 - a square tolerance allowing to decide whether a point is on the shape
809 * \param [in] newSolution - position on the shape (U or UV) of the point found
811 * \param [in] prevSolution - position on the shape (U or UV) of a neighbor point
812 * \return bool - \c true if the point lies on the boundary shape
814 * This method is used to select a shape by checking if all neighbor nodes of a node to move
817 //================================================================================
819 bool FT_Projector::isOnShape( const gp_Pnt& point,
822 const double* prevSolution)
824 if ( _bndBox.IsOut( point ) || !_realProjector )
828 if ( isPlanarBoundary() )
829 return projectAndClassify( point, tol2, proj, newSolution, prevSolution );
831 return project( point, tol2, proj, newSolution, prevSolution );
834 //================================================================================
836 * \brief Project a point to the boundary shape
837 * \param [in] point - the point to project
838 * \param [in] maxDist2 - the maximal square distance between the point and the projection
839 * \param [out] projection - the projection
840 * \param [out] newSolution - position on the shape (U or UV) of the point found
842 * \param [in] prevSolution - already found position on the shape (U or UV) of a neighbor point
843 * \return bool - false if the distance between the point and the projection
844 * is more than sqrt(maxDist2)
846 * This method is used to project a node in the case where only one shape is found by name
848 //================================================================================
850 bool FT_Projector::project( const gp_Pnt& point,
851 const double maxDist2,
854 const double* prevSolution)
856 if ( !_realProjector )
859 _realProjector->_dist = 1e100;
860 projection = _realProjector->project( point, newSolution, prevSolution );
862 return ( _realProjector->_dist * _realProjector->_dist < maxDist2 );
865 //================================================================================
867 * \brief Project a point to the boundary shape and check if the projection lies within
869 * \param [in] point - the point to project
870 * \param [in] maxDist2 - the maximal square distance between the point and the projection
871 * \param [out] projection - the projection
872 * \param [out] newSolution - position on the shape (U or UV) of the point found
874 * \param [in] prevSolution - already found position on the shape (U or UV) of a neighbor point
875 * \return bool - false if the projection point lies out of the shape boundary or
876 * the distance between the point and the projection is more than sqrt(maxDist2)
878 * This method is used to project a node in the case where several shapes are selected for
879 * projection of a node group
881 //================================================================================
883 bool FT_Projector::projectAndClassify( const gp_Pnt& point,
884 const double maxDist2,
887 const double* prevSolution)
889 if ( _bndBox.IsOut( point ) || !_realProjector )
892 return _realProjector->projectAndClassify( point, maxDist2, projection,
893 newSolution, prevSolution );
896 //================================================================================
898 * \brief Return true if a previously found solution can be used to speed up the projection
900 //================================================================================
902 bool FT_Projector::canUsePrevSolution() const
904 return ( _realProjector && _realProjector->canUsePrevSolution() );