X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FHYDROData%2FHYDROData_ChannelAltitude.cxx;h=413685f83f3ddbc4a8874ec8de21e856ee2d10c5;hb=cde2ec476486fcd7c9b7b38ce814c648d73e7fd3;hp=0070f9c32a917419e372d252dc55acdd3d5d5fbe;hpb=13dcd7edcf93135429fce003da064297775ac11d;p=modules%2Fhydro.git diff --git a/src/HYDROData/HYDROData_ChannelAltitude.cxx b/src/HYDROData/HYDROData_ChannelAltitude.cxx index 0070f9c3..413685f8 100644 --- a/src/HYDROData/HYDROData_ChannelAltitude.cxx +++ b/src/HYDROData/HYDROData_ChannelAltitude.cxx @@ -20,16 +20,38 @@ #include "HYDROData_Document.h" #include "HYDROData_Object.h" +#include "HYDROData_Channel.h" #include "HYDROData_Projection.h" +#include "HYDROData_Polyline3D.h" +#include "HYDROData_PolylineXY.h" +#include "HYDROData_ProfileUZ.h" +#include "HYDROData_Profile.h" #define _DEVDEBUG_ #include "HYDRO_trace.hxx" #include -#include +#include +#include +#include +#include +#include +#include #include +#include +#include +#include +#include +#include +#include +#include #include +#include + +#include +#include +#include IMPLEMENT_STANDARD_HANDLE(HYDROData_ChannelAltitude, HYDROData_IAltitudeObject) IMPLEMENT_STANDARD_RTTIEXT(HYDROData_ChannelAltitude, HYDROData_IAltitudeObject) @@ -45,36 +67,261 @@ HYDROData_ChannelAltitude::~HYDROData_ChannelAltitude() double HYDROData_ChannelAltitude::GetAltitudeForPoint( const gp_XY& thePoint ) const { - DEBTRACE("HYDROData_ChannelAltitude::GetAltitudeForPoint"); + DEBTRACE("GetAltitudeForPoint p(" << thePoint.X() << ", " << thePoint.Y() << ")"); double aResAltitude = GetInvalidAltitude(); - Handle(HYDROData_Object) anObject = - Handle(HYDROData_Object)::DownCast( GetFatherObject() ); - if ( anObject.IsNull() ) - { - DEBTRACE("---"); - return aResAltitude; - } - - TopoDS_Shape anObjectShape3D = anObject->GetShape3D(); - DEBTRACE("object: " << anObject->GetName().toStdString()); - if ( anObjectShape3D.IsNull() ) - { - DEBTRACE("---"); - return aResAltitude; - } - else - { - DEBTRACE("anObjectShape3D type " << anObjectShape3D.ShapeType()); - BRepTools::Write(anObjectShape3D, "digue3D.brep"); - } - - HYDROData_Make3dMesh aMesher3D( anObjectShape3D, Precision::Intersection() ); - - gp_Pnt aHighestPoint; - if ( aMesher3D.GetHighestOriginal( thePoint.X(), thePoint.Y(), aHighestPoint ) ) - aResAltitude = aHighestPoint.Z(); - DEBTRACE("aResAltitude=" << aResAltitude); + Handle(HYDROData_Channel) aChannel = + Handle(HYDROData_Channel)::DownCast(GetFatherObject()); + if (aChannel.IsNull()) + { + DEBTRACE("aChannel.IsNull()"); + return aResAltitude; + } + DEBTRACE("aChannel: " << aChannel->GetName().toStdString()); + + Handle(HYDROData_Polyline3D) aGuideLine = aChannel->GetGuideLine(); + if (aGuideLine.IsNull()) + { + DEBTRACE("aGuideLine.IsNull()"); + return aResAltitude; + } + //DEBTRACE("aGuideLine: " << aGuideLine->GetName().toStdString()); + + Handle(HYDROData_PolylineXY) aGuideXY = aGuideLine->GetPolylineXY(); + if (aGuideXY.IsNull()) + { + DEBTRACE("aGuideXY.IsNull()"); + return aResAltitude; + } + //DEBTRACE("aGuideXY: " << aGuideXY->GetName().toStdString()); + + Handle(HYDROData_ProfileUZ) aGuideUZ = aGuideLine->GetProfileUZ(); + if (aGuideUZ.IsNull()) + { + aGuideUZ = aGuideLine->GetChildProfileUZ(); // profile obtained from bathymetry + } + if (aGuideUZ.IsNull()) + { + DEBTRACE("aGuideUZ.IsNull()"); + return aResAltitude; + } + //DEBTRACE("aGuideUZ: " << aGuideUZ->GetName().toStdString()); + + Handle (HYDROData_Profile) aProfile = aChannel->GetProfile(); + if (aProfile.IsNull()) + { + return aResAltitude; + } + //DEBTRACE("aProfile: " << aProfile->GetName().toStdString()); + + // --- See GEOMImpl_ProjectionDriver.cxx + + TopoDS_Shape aShape = aGuideXY->GetShape(); + gp_Pnt P1(thePoint.X(), thePoint.Y(), 0); + TopoDS_Shape aPoint = BRepBuilderAPI_MakeVertex(P1).Shape(); + + if (aPoint.IsNull() || aShape.IsNull()) + { + DEBTRACE("aPoint.IsNull() || aShape.IsNull()"); + return aResAltitude; + } + + if (aShape.ShapeType() != TopAbs_EDGE && aShape.ShapeType() != TopAbs_WIRE) + { + DEBTRACE("Projection aborted : the shape is neither an edge nor a wire"); + return aResAltitude; + } + + // Perform projection. + BRepExtrema_DistShapeShape aDistShSh(aPoint, aShape, Extrema_ExtFlag_MIN); + + if (aDistShSh.IsDone() == Standard_False) + { + DEBTRACE("Projection not done"); + return aResAltitude; + } + + Standard_Boolean hasValidSolution = Standard_False; + Standard_Integer aNbSolutions = aDistShSh.NbSolution(); + Standard_Integer i; + double aParam = 0.; + Standard_Real aTolConf = BRep_Tool::Tolerance(TopoDS::Vertex(aPoint)); + Standard_Real aTolAng = 1.e-4; + + for (i = 1; i <= aNbSolutions; i++) + { + Standard_Boolean isValid = Standard_False; + BRepExtrema_SupportType aSupportType = aDistShSh.SupportTypeShape2(i); + TopoDS_Shape aSupportShape = aDistShSh.SupportOnShape2(i); + + if (aSupportType == BRepExtrema_IsOnEdge) + { + // Minimal distance inside edge is really a projection. + isValid = Standard_True; + aDistShSh.ParOnEdgeS2(i, aParam); + } + else if (aSupportType == BRepExtrema_IsVertex) + { + TopExp_Explorer anExp(aShape, TopAbs_EDGE); + + if (aDistShSh.Value() <= aTolConf) + { + // The point lies on the shape. This means this point + // is really a projection. + for (; anExp.More() && !isValid; anExp.Next()) + { + TopoDS_Edge aCurEdge = TopoDS::Edge(anExp.Current()); + + if (aCurEdge.IsNull() == Standard_False) + { + TopoDS_Vertex aVtx[2]; + + TopExp::Vertices(aCurEdge, aVtx[0], aVtx[1]); + + for (int j = 0; j < 2; j++) + { + if (aSupportShape.IsSame(aVtx[j])) + { + // The current edge is a projection edge. + isValid = Standard_True; + aSupportShape = aCurEdge; + aParam = BRep_Tool::Parameter(aVtx[j], aCurEdge); + break; + } + } + } + } + } + else + { + // Minimal distance to vertex is not always a real projection. + gp_Pnt aPnt = BRep_Tool::Pnt(TopoDS::Vertex(aPoint)); + gp_Pnt aPrjPnt = BRep_Tool::Pnt(TopoDS::Vertex(aSupportShape)); + gp_Vec aDProjP(aPrjPnt, aPnt); + + for (; anExp.More() && !isValid; anExp.Next()) + { + TopoDS_Edge aCurEdge = TopoDS::Edge(anExp.Current()); + + if (aCurEdge.IsNull() == Standard_False) + { + TopoDS_Vertex aVtx[2]; + + TopExp::Vertices(aCurEdge, aVtx[0], aVtx[1]); + + for (int j = 0; j < 2; j++) + { + if (aSupportShape.IsSame(aVtx[j])) + { + // Check if the point is a projection to the current edge. + Standard_Real anEdgePars[2]; + Handle(Geom_Curve) aCurve = BRep_Tool::Curve(aCurEdge, anEdgePars[0], anEdgePars[1]); + gp_Pnt aVal; + gp_Vec aD1; + + aParam = BRep_Tool::Parameter(aVtx[j], aCurEdge); + aCurve->D1(aParam, aVal, aD1); + + if (Abs(aD1.Dot(aDProjP)) <= aTolAng) + { + // The current edge is a projection edge. + isValid = Standard_True; + aSupportShape = aCurEdge; + break; + } + } + } + } + } + } + } + + if (isValid) + { + if (hasValidSolution) + { + DEBTRACE("Projection aborted : multiple solutions"); + return aResAltitude; + } + + // Store the valid solution. + hasValidSolution = Standard_True; + + // profile altitude at projection point + HYDROData_IPolyline::PointsList aProfilePoints = aGuideUZ->GetPoints(); + if ( aProfilePoints.IsEmpty() ) + { + DEBTRACE("empty profile UZ"); + return aResAltitude; + } + double aDepth = HYDROData_ProfileUZ::GetDepthFromDistance( aProfilePoints, aParam ); + //DEBTRACE("profile altitude: " << aDepth); + + // Compute edge index. + TopExp_Explorer anExp(aShape, TopAbs_EDGE); + int anIndex = 0; + for (; anExp.More(); anExp.Next(), anIndex++) + { + if (aSupportShape.IsSame(anExp.Current())) + { + break; + } + } + + // get the XY distance from point to guideline + const gp_Pnt &aPntProj = aDistShSh.PointOnShape2(i); + //DEBTRACE("projection: (" << aPntProj.X() << ", " << aPntProj.Y() << ", " << aPntProj.Z() << ")"); + gp_XY aProjXY = gp_XY(aPntProj.X(), aPntProj.Y()); + aProjXY.Subtract(thePoint); + double distance = aProjXY.Modulus(); + //DEBTRACE("distance to guideline " << distance); + + // get delta altitude on section (supposed symmetric) from guideline distance (aParam) + double delta = 0; + int i1 = 0; + gp_XY pt1 = gp_XY(); + gp_XY pt2 = gp_XY(); + HYDROData_ProfileUZ::PointsList aSectionPoints = aProfile->GetParametricPoints(); + for ( int i = 1, aNbPoints = aSectionPoints.Size(); i <= aNbPoints; ++i ) + { + const HYDROData_IPolyline::Point& aPolylinePoint = aSectionPoints.Value( i ); + //DEBTRACE(" profile point: " << aPolylinePoint.X() << " " << aPolylinePoint.Y()); + if (aPolylinePoint.X() < distance) + { + i1 = i; + pt1 = aPolylinePoint; + } + if (aPolylinePoint.X() >= distance) + { + pt2 = aPolylinePoint; + break; + } + } + if ((i1 == 0) && (distance > 0)) + { + DEBTRACE("Projection aborted : non centered profile"); + return aResAltitude; + } + if (i1 == aProfilePoints.Size()) // distance >= profile width + { + delta = pt1.Y(); + } + else + { + delta = pt1.Y() + (pt2.Y() - pt1.Y())*(distance -pt1.X())/(pt2.X()-pt1.X()); + } + aResAltitude = delta + aDepth; + DEBTRACE("distance XY: "<< aParam << " distance to guideline: " << distance << " final altitude: " << aResAltitude << " delta: " << delta); + return aResAltitude; + } + } + + if (!hasValidSolution) + { + DEBTRACE("Projection aborted : no projection"); + return aResAltitude; + } + return aResAltitude; }