X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FGEOMImpl%2FGEOMImpl_ProjectionDriver.cxx;h=57d8422425912ad1194b4a15c270a8fcf92bee0f;hb=31b91717e01915431d5658a7054af18a7b7044d5;hp=3e025ccd04f992b1c35728dd465824964e3d5cd9;hpb=c481b6871aad775ca8575f471a44b87828167e78;p=modules%2Fgeom.git diff --git a/src/GEOMImpl/GEOMImpl_ProjectionDriver.cxx b/src/GEOMImpl/GEOMImpl_ProjectionDriver.cxx index 3e025ccd0..57d842242 100644 --- a/src/GEOMImpl/GEOMImpl_ProjectionDriver.cxx +++ b/src/GEOMImpl/GEOMImpl_ProjectionDriver.cxx @@ -1,4 +1,4 @@ -// Copyright (C) 2007-2014 CEA/DEN, EDF R&D, OPEN CASCADE +// Copyright (C) 2007-2016 CEA/DEN, EDF R&D, OPEN CASCADE // // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS @@ -26,16 +26,28 @@ #include #include +#include #include #include +#include +#include +#include +#include +#include #include +#include #include +#include +#include #include +#include #include #include +#include #include #include +#include #include #include @@ -44,11 +56,14 @@ #include #include #include -#include +#include +#include #include #include +#include #include +#include #include #include @@ -78,7 +93,7 @@ GEOMImpl_ProjectionDriver::GEOMImpl_ProjectionDriver() //function : Execute //purpose : //======================================================================= -Standard_Integer GEOMImpl_ProjectionDriver::Execute(TFunction_Logbook& log) const +Standard_Integer GEOMImpl_ProjectionDriver::Execute(LOGBOOK& log) const { if (Label().IsNull()) return 0; Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction(Label()); @@ -232,7 +247,11 @@ Standard_Integer GEOMImpl_ProjectionDriver::Execute(TFunction_Logbook& log) cons if (aShape.IsNull()) return 0; aFunction->SetValue(aShape); - log.SetTouched(Label()); +#if OCC_VERSION_MAJOR < 7 + log.SetTouched(Label()); +#else + log->SetTouched(Label()); +#endif } else if (aType == PROJECTION_ON_WIRE) { // Perform projection of point on a wire or an edge. GEOMImpl_IProjection aProj (aFunction); @@ -400,6 +419,43 @@ Standard_Integer GEOMImpl_ProjectionDriver::Execute(TFunction_Logbook& log) cons if (!hasValidSolution) { Standard_ConstructionError::Raise("Projection aborted : no projection"); } + } else if (aType == PROJECTION_ON_CYLINDER) { + GEOMImpl_IProjOnCyl aProj (aFunction); + Handle(GEOM_Function) aShapeFunction = aProj.GetShape(); + + if (aShapeFunction.IsNull()) { + return 0; + } + + TopoDS_Shape aShape = aShapeFunction->GetValue(); + + if (aShape.IsNull()) { + return 0; + } + + // Get the face. + const TopAbs_ShapeEnum aType = aShape.ShapeType(); + const Standard_Real aRadius = aProj.GetRadius(); + const Standard_Real aStartAngle = aProj.GetStartAngle(); + const Standard_Real aLengthAngle = aProj.GetAngleLength(); + const Standard_Real aRotationAngle = aProj.GetAngleRotation(); + + if (aType != TopAbs_WIRE && aType != TopAbs_FACE) { + return 0; + } + + if (aRadius <= Precision::Confusion()) { + return 0; + } + + TopoDS_Shape aProjShape = projectOnCylinder + (aShape, aRadius, aStartAngle, aLengthAngle, aRotationAngle); + + if (aProjShape.IsNull()) { + return 0; + } + + aFunction->SetValue(aProjShape); } return 1; @@ -424,28 +480,331 @@ GetCreationInformation(std::string& theOperationName, switch ( aType ) { case PROJECTION_COPY: - { - GEOMImpl_IMirror aCI( function ); + { + GEOMImpl_IMirror aCI( function ); - AddParam( theParams, "Source object", aCI.GetOriginal() ); - AddParam( theParams, "Target face", aCI.GetPlane() ); - break; - } + AddParam( theParams, "Source object", aCI.GetOriginal() ); + AddParam( theParams, "Target face", aCI.GetPlane() ); + break; + } case PROJECTION_ON_WIRE: - { - GEOMImpl_IProjection aProj (function); + { + GEOMImpl_IProjection aProj (function); + + AddParam(theParams, "Point", aProj.GetPoint()); + AddParam(theParams, "Shape", aProj.GetShape()); - AddParam(theParams, "Point", aProj.GetPoint()); - AddParam(theParams, "Shape", aProj.GetShape()); + break; + } + case PROJECTION_ON_CYLINDER: + { + theOperationName = "PROJ_ON_CYL"; + + GEOMImpl_IProjOnCyl aProj (function); + const Standard_Real aLengthAngle = aProj.GetAngleLength(); - break; + AddParam(theParams, "Shape", aProj.GetShape()); + AddParam(theParams, "Radius", aProj.GetRadius()); + AddParam(theParams, "Start angle", aProj.GetStartAngle()); + + if (aLengthAngle >= 0.) { + AddParam(theParams, "Length angle", aLengthAngle); } + + AddParam(theParams, "Rotation angle", aProj.GetAngleRotation()); + + break; + } default: return false; } - + return true; } -IMPLEMENT_STANDARD_HANDLE (GEOMImpl_ProjectionDriver,GEOM_BaseDriver); -IMPLEMENT_STANDARD_RTTIEXT (GEOMImpl_ProjectionDriver,GEOM_BaseDriver); +//================================================================================ +/*! + * \brief Performs projection of a planar wire or a face on a cylinder. + */ +//================================================================================ + +TopoDS_Shape GEOMImpl_ProjectionDriver::projectOnCylinder + (const TopoDS_Shape &theShape, + const Standard_Real theRadius, + const Standard_Real theStartAngle, + const Standard_Real theAngleLength, + const Standard_Real theAngleRotation) const +{ + TopoDS_Shape aResult; + + // Get the face. + const TopAbs_ShapeEnum aType = theShape.ShapeType(); + TopoDS_Face aFace; + + if (aType == TopAbs_WIRE) { + // Try to create a planar face. + TopoDS_Wire aWire = TopoDS::Wire(theShape); + BRepBuilderAPI_MakeFace aMkFace(aWire, Standard_True); + + if (aMkFace.IsDone()) { + aFace = aMkFace.Face(); + } else { + // Check if the wire is a straight line. + TopExp_Explorer anEExp(aWire, TopAbs_EDGE); + TopoDS_Edge anEdge; + + for (; anEExp.More(); anEExp.Next()) { + anEdge = TopoDS::Edge(anEExp.Current()); + + if (!BRep_Tool::Degenerated(anEdge)) { + break; + } + } + + if (anEExp.More()) { + // Not degenerated edge found. Try to create a plane. + Standard_Real aPar[2]; + Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aPar[0], aPar[1]); + gp_Pnt aP0 = aCurve->Value(aPar[0]); + gp_Pnt aP1 = aCurve->Value(0.5*(aPar[1] + aPar[0])); + gp_Vec aX(aP1.XYZ().Subtracted(aP0.XYZ())); + Standard_Real aTolConf = Precision::Confusion(); + + if (aX.Magnitude() > aTolConf) { + aX.Normalize(); + + // Get the plane normal ortogonal to Z axis. + gp_Vec aZ(0., 0., 1.); + gp_Vec aN = aX.Crossed(aZ); + + if (aN.Magnitude() <= aTolConf) { + // aX is parallel to aZ. Get the plane normal ortogonal to Y axis. + gp_Vec aY(0., 1., 0.); + + aN = aX.Crossed(aY); + } + + if (aN.Magnitude() > aTolConf) { + gp_Ax3 anAxis(aP0, gp_Dir(aN), gp_Dir(aX)); + Handle(Geom_Plane) aPlane = new Geom_Plane(anAxis); + BRepBuilderAPI_MakeFace aMkFace(aPlane, aWire); + + if (aMkFace.IsDone()) { + aFace = aMkFace.Face(); + } + } + } + } + } + } else if (aType == TopAbs_FACE) { + aFace = TopoDS::Face(theShape); + } + + if (aFace.IsNull()) { + return aResult; + } + + // Compute 2d translation transformation. + TopoDS_Wire anOuterWire = BRepTools::OuterWire(aFace); + BRepTools_WireExplorer aOWExp(anOuterWire, aFace); + + if (!aOWExp.More()) { + // NEVERREACHED + return aResult; + } + + // Rotate 2D presentation of face. + TopoDS_Vertex aFirstVertex = aOWExp.CurrentVertex(); + TopoDS_Edge aFirstEdge = aOWExp.Current(); + gp_Pnt aPnt = BRep_Tool::Pnt(aFirstVertex); + BRepAdaptor_Curve2d anAdaptorCurve(aFirstEdge, aFace); + Standard_Real aParam = + BRep_Tool::Parameter(aFirstVertex, aFirstEdge, aFace); + gp_Pnt2d aPntUV; + gp_Vec2d aVecUV; + gp_Vec2d aVecU0(1., 0); + + anAdaptorCurve.D1(aParam, aPntUV, aVecUV); + + if (aVecUV.Magnitude() <= gp::Resolution()) { + return aResult; + } + + if (aFirstEdge.Orientation() == TopAbs_REVERSED) { + aVecUV.Reverse(); + } + + const Standard_Real anAngle = aVecUV.Angle(aVecU0) + theAngleRotation; + const Standard_Boolean isToRotate = Abs(anAngle) > Precision::Angular(); + gp_Trsf2d aRotTrsf; + Bnd_Box2d aUVBox; + Standard_Real aPar[2]; + + if (isToRotate) { + aRotTrsf.SetRotation(aPntUV, anAngle); + } + + for (; aOWExp.More(); aOWExp.Next()) { + TopoDS_Edge anEdge = aOWExp.Current(); + Handle(Geom2d_Curve) aCurve = + BRep_Tool::CurveOnSurface(anEdge, aFace, aPar[0], aPar[1]); + + if (aCurve.IsNull()) { + continue; + } + + if (isToRotate) { + aCurve = Handle(Geom2d_Curve)::DownCast(aCurve->Transformed(aRotTrsf)); + } + + BndLib_Add2dCurve::Add(aCurve, aPar[0], aPar[1], 0., aUVBox); + } + + Standard_Real aU[2]; + Standard_Real aV[2]; + + aUVBox.Get(aU[0], aV[0], aU[1], aV[1]); + + // Compute anisotropic transformation from a face's 2d space + // to cylinder's 2d space. + GEOMUtils::Trsf2d aTrsf2d + (1./theRadius, 0., theStartAngle - aU[0]/theRadius, + 0., 1., aPnt.Z() - aPntUV.Y()); + + // Compute scaling trsf. + const Standard_Boolean isToScale = theAngleLength >= Precision::Angular(); + gp_Trsf2d aScaleTrsf; + + if (isToScale) { + // Perform 2d scaling. + gp_Pnt2d aMidPnt(0.5*(aU[1] + aU[0]), 0.5*(aV[1] + aV[0])); + const Standard_Real aScaleFactor = theAngleLength*theRadius/(aU[1] - aU[0]); + + aTrsf2d.TransformD0(aMidPnt); + + aScaleTrsf.SetScale(aMidPnt, aScaleFactor); + } + + // Get 2d presentation of a face. + Handle(Geom_Surface) aCylinder = + new Geom_CylindricalSurface(gp_Ax3(), theRadius); + GeomAdaptor_Surface aGACyl(aCylinder); + TopExp_Explorer anExp(aFace, TopAbs_WIRE); + TopTools_ListOfShape aWires; + Standard_Real aUResol = aGACyl.UResolution(Precision::Confusion()); + Standard_Real aVResol = aGACyl.VResolution(Precision::Confusion()); + + for (; anExp.More(); anExp.Next()) { + TopoDS_Wire aWire = TopoDS::Wire(anExp.Current()); + BRepTools_WireExplorer aWExp(aWire, aFace); + BRepBuilderAPI_MakeWire aMkWire; + + for (; aWExp.More(); aWExp.Next()) { + TopoDS_Edge anEdge = aWExp.Current(); + Handle(Geom2d_Curve) aCurve = + BRep_Tool::CurveOnSurface(anEdge, aFace, aPar[0], aPar[1]); + + if (aCurve.IsNull()) { + continue; + } + + if (isToRotate) { + aCurve = Handle(Geom2d_Curve)::DownCast(aCurve->Transformed(aRotTrsf)); + } + + // Transform the curve to cylinder's parametric space. +#if OCC_VERSION_MAJOR < 7 + GEOMUtils::Handle(HTrsfCurve2d) aTrsfCurve = +#else + Handle(GEOMUtils::HTrsfCurve2d) aTrsfCurve = +#endif + new GEOMUtils::HTrsfCurve2d(aCurve, aPar[0], aPar[1], aTrsf2d); + Approx_Curve2d aConv (aTrsfCurve, aPar[0], aPar[1], + aUResol, aVResol, GeomAbs_C1, + 9, 1000); + + if (!aConv.IsDone() && !aConv.HasResult()) { + return aResult; + } + + Handle(Geom2d_Curve) aCylCurve = aConv.Curve(); + + if (isToScale) { + aCylCurve->Transform(aScaleTrsf); + } + + // Create edge and add it to the wire. + BRepBuilderAPI_MakeEdge aMkEdge(aCylCurve, aCylinder); + + if (!aMkEdge.IsDone()) { + return aResult; + } + + aMkWire.Add(aMkEdge.Edge()); + + if (!aMkWire.IsDone()) { + return aResult; + } + } + + if (aWire.IsSame(anOuterWire)) { + // Make the outer wire first. + aWires.Prepend(aMkWire.Wire()); + } else { + aWires.Append(aMkWire.Wire()); + } + } + + // Create a face. + if (aWires.IsEmpty()) { + return aResult; + } + + TopTools_ListIteratorOfListOfShape aWIter(aWires); + TopoDS_Wire aWire = TopoDS::Wire(aWIter.Value()); + BRepBuilderAPI_MakeFace aMkFace(aCylinder, aWire); + + if (!aMkFace.IsDone()) { + return aResult; + } + + for (aWIter.Next(); aWIter.More(); aWIter.Next()) { + aWire = TopoDS::Wire(aWIter.Value()); + aMkFace.Add(aWire); + + if (!aMkFace.IsDone()) { + return aResult; + } + } + + // Build 3D curves. + TopoDS_Face aCylFace = aMkFace.Face(); + TopoDS_Shape aResShape; + + BRepLib::BuildCurves3d(aCylFace); + + // Check shape. + if (aType == TopAbs_WIRE) { + TopExp_Explorer aResExp(aCylFace, TopAbs_WIRE); + + if (aResExp.More()) { + aResShape = aResExp.Current(); + } + } else { + aResShape = aCylFace; + } + + if (aResShape.IsNull() == Standard_False) { + if (!GEOMUtils::CheckShape(aResShape, true)) { + if (!GEOMUtils::FixShapeTolerance(aResShape)) { + return aResult; + } + } + + aResult = aResShape; + } + + return aResult; +} + +OCCT_IMPLEMENT_STANDARD_RTTIEXT (GEOMImpl_ProjectionDriver,GEOM_BaseDriver);