+/**
+ * Restore the viewer state after the curve modification is done.
+ * Open local context and select given points inside it.
+ * \param thePoints a list of curve selected points
+ */
+void CurveCreator_Widget::finishCurveModification(
+ const CurveCreator_Widget::SectionToPointList& thePoints )
+{
+ if ( getActionMode() == ModificationMode )
+ setLocalPointContext( true );
+ setSelectedPonts( thePoints );
+ updateUndoRedo();
+}
+
+/**
+ * Returns a point index in the model curve by the point coordinates in the viewer
+ * \param theX the X coordinate of the point
+ * \param theY the Y coordinate of the point
+ */
+int CurveCreator_Widget::findLocalPointIndex( int theSectionId, float theX, float theY )
+{
+ int aPntIndex = -1;
+
+ CurveCreator::Coordinates aCoords;
+ for ( int i = 0, aNb = myCurve->getNbPoints( theSectionId ); i < aNb && aPntIndex < 0; i++ ) {
+ aCoords = myCurve->getPoint( theSectionId, i );
+ if ( aCoords.size() < 2 )
+ continue;
+ if ( fabs( aCoords[0] - theX ) < LOCAL_SELECTION_TOLERANCE &&
+ fabs( aCoords[1] - theY ) < LOCAL_SELECTION_TOLERANCE )
+ aPntIndex = i;
+ }
+
+ return aPntIndex;
+}
+
+void CurveCreator_Widget::findSectionsToPoints( const double theX, const double theY,
+ CurveCreator_Widget::SectionToPointList& thePoints )
+{
+ thePoints.clear();
+
+ int aPointId = -1;
+ for ( int i = 0, aNb = myCurve->getNbSections(); i < aNb; i++ ) {
+ aPointId = findLocalPointIndex( i, theX, theY );
+ if ( aPointId < 0 )
+ continue;
+ SectionToPoint aPoint = std::make_pair( i, aPointId );
+ if ( !contains( thePoints, aPoint ) )
+ thePoints.push_back( aPoint );
+ }
+}
+
+void CurveCreator_Widget::convert( const SectionToPointList& thePoints,
+ QMap<int, QList<int> >& theConvPoints )
+{
+ theConvPoints.clear();
+
+ SectionToPointList::const_iterator anIt = thePoints.begin(), aLast = thePoints.end();
+ QList<int> aPoints;
+ int aSectionId, aPointId;
+ for ( ; anIt != aLast; anIt++ ) {
+ aSectionId = anIt->first;
+ aPointId = anIt->second;
+ aPoints.clear();
+ if ( theConvPoints.contains( aSectionId ) )
+ aPoints = theConvPoints[aSectionId];
+ if ( aPoints.contains( aPointId ) )
+ continue;
+ aPoints.append( aPointId );
+ theConvPoints[aSectionId] = aPoints;
+ }
+}
+
+/**
+ * Checks whether the point belongs to the OCC object
+ * \param theObject a line or shape with a bspline inside
+ * \param theX the X coordinate in the view.
+ * \param theY the Y coordinate in the view.
+ * \param thePoint the output point to be append to the model curve
+ * \param thePoint1 the output point to bound the line where a new point should be inserted
+ * \param thePoint2 the output point to bound the line where a new point should be inserted
+ */
+bool CurveCreator_Widget::pointOnObject( Handle(AIS_InteractiveObject) theObject,
+ const int theX, const int theY,
+ gp_Pnt& thePoint,
+ gp_Pnt& thePoint1, gp_Pnt& thePoint2 )
+{
+ bool isFound = false;
+
+ OCCViewer_Viewer* aViewer = getOCCViewer();
+ if ( theObject.IsNull() || !aViewer )
+ return isFound;
+
+ gp_Pnt aPoint;
+ Standard_Real aParameter;
+ gp_Pnt aPnt1, aPnt2;
+ Handle(AIS_Line) aLine = Handle(AIS_Line)::DownCast( theObject );
+ if ( !aLine.IsNull() ) {
+ const Handle(Geom_Line) aGLine = aLine->Line();
+ isFound = hasProjectPointOnCurve( theX, theY, aGLine, aParameter );
+ if ( isFound ) {
+ aPoint = aGLine->Value( aParameter );
+
+ Handle(Geom_Point) aPStart;
+ Handle(Geom_Point) aPEnd;
+ aLine->Points( aPStart, aPEnd );
+ aPnt1 = aPStart->Pnt();
+ aPnt2 = aPEnd->Pnt();
+
+ // in case of Geom line a projection is performed to the infinite line,
+ // so it is necessary to bound it by the line size
+ Bnd_Box aLineBox;
+ aLineBox.Set( aPnt1, gp_Vec( aPnt1, aPnt2 ) );
+ isFound = !aLineBox.IsOut( aPoint );
+ }
+ }
+ else {
+ Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast( theObject );
+ if ( !aShape.IsNull() ) {
+ const TopoDS_Wire& aWire = TopoDS::Wire( aShape->Shape() );
+ if ( !aWire.IsNull() ) {
+ TopExp_Explorer anExp( aWire, TopAbs_EDGE );
+ for ( ; anExp.More(); anExp.Next())
+ {
+ const TopoDS_Edge& anEdge = TopoDS::Edge(anExp.Current());
+ if ( !anEdge.IsNull() ) {
+ Standard_Real aFirst, aLast;
+ Handle(Geom_Curve) aCurve = BRep_Tool::Curve( anEdge, aFirst, aLast );
+
+ if ( aCurve->IsKind( STANDARD_TYPE(Geom_BSplineCurve) ) ) {
+ Handle(Geom_BSplineCurve) aBSplineCurve = Handle(Geom_BSplineCurve)::DownCast( aCurve );
+ if ( !aBSplineCurve.IsNull() ) {
+ isFound = hasProjectPointOnCurve( theX, theY, aCurve, aParameter );
+ if ( isFound ) {
+ aPoint = aBSplineCurve->Value( aParameter );
+ Standard_Integer anI1, anI2;
+ aBSplineCurve->LocateU( aParameter, LOCAL_SELECTION_TOLERANCE, anI1, anI2 );
+
+ aPnt1 = aBSplineCurve->Value( aBSplineCurve->Knot( anI1 ) );
+ aPnt2 = aBSplineCurve->Value( aBSplineCurve->Knot( anI2 ) );
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ if ( isFound ) {
+ thePoint = aPoint;
+ thePoint1 = aPnt1;
+ thePoint2 = aPnt2;
+ }
+ return isFound;
+}
+
+/**
+ * Returns whether the clicked point belong to the curve or has a very near projection
+ * \param theX the X coordinate of a point clicked in the OCC viewer
+ * \param theY the Y coordinate of a point clicked in the OCC viewer
+ * \param theCurve a geometry curve
+ * \param theOutPoint a found projected point on the curve
+ */
+bool CurveCreator_Widget::hasProjectPointOnCurve( const int theX, const int theY,
+ const Handle(Geom_Curve)& theCurve,
+ Standard_Real& theParameter )
+{
+ bool isFound = false;
+ OCCViewer_Viewer* aViewer = getOCCViewer();
+ if ( !aViewer )
+ return isFound;
+
+ OCCViewer_ViewWindow* aWindow =
+ (OCCViewer_ViewWindow*)aViewer->getViewManager()->getActiveView();
+ Handle(V3d_View) aView = aWindow->getViewPort()->getView();
+ gp_Pnt aPoint = CurveCreator_Utils::ConvertClickToPoint( theX, theY, aView );
+
+ GeomAPI_ProjectPointOnCurve aProj( aPoint, theCurve );
+ Standard_Integer aNbPoint = aProj.NbPoints();
+ if (aNbPoint > 0) {
+ for (Standard_Integer j = 1; j <= aNbPoint && !isFound; j++) {
+ gp_Pnt aNewPoint = aProj.Point( j );
+ theParameter = aProj.Parameter( j );
+
+ int aX, anY;
+ CurveCreator_Utils::ConvertPointToClick( aNewPoint, aView, aX, anY );
+
+ int aXDelta = abs( aX - theX );
+ int anYDelta = abs( anY - theY );
+ isFound = aXDelta < SCENE_PIXEL_TOLERANCE && anYDelta < SCENE_PIXEL_TOLERANCE;
+ }
+ }
+ return isFound;
+}
+
+/**
+ * Returns a section index from the table
+ * \param theRowId a table row
+ */
+int CurveCreator_Widget::getSectionId( const int theRowId ) const
+{
+ return myLocalPointView->item( theRowId, 0 )->data( Qt::UserRole ).toInt();
+}
+
+/**
+ * Returns a point index from the table
+ * \param theRowId a table row
+ */
+int CurveCreator_Widget::getPointId( const int theRowId ) const
+{
+ return myLocalPointView->item( theRowId, 1 )->data( Qt::UserRole ).toInt();
+}
+
+/**
+ * Returns whethe the container has the value
+ * \param theList a container of values
+ * \param theValue a value
+ */
+bool CurveCreator_Widget::contains( const CurveCreator_Widget::SectionToPointList& theList,
+ const CurveCreator_Widget::SectionToPoint& theValue ) const
+{
+ bool isFound = false;
+
+ SectionToPointList::const_iterator anIt = theList.begin(), aLast = theList.end();
+ for ( ; anIt != aLast && !isFound; anIt++ )
+ isFound = anIt->first == theValue.first && anIt->second == theValue.second;
+
+ return isFound;
+}