--- /dev/null
+// File: Hydro_Projections.cxx
+// Created: 11.12.13 17:47:42
+// Author: jgv@ROLEX
+// Copyright: Open CASCADE 2013
+
+#include <HYDROData_Projection.h>
+#include <BRepAdaptor_Curve.hxx>
+#include <BRep_Builder.hxx>
+#include <BRepBuilderAPI_Sewing.hxx>
+#include <BRepLib.hxx>
+#include <BRepLib_MakeEdge.hxx>
+#include <BRepLib_MakeFace.hxx>
+#include <BRepExtrema_DistShapeShape.hxx>
+#include <Bnd_Box.hxx>
+#include <BRepBndLib.hxx>
+#include <gp_Pnt.hxx>
+#include <gp_Lin.hxx>
+#include <HLRAlgo_Projector.hxx>
+#include <HLRBRep_Algo.hxx>
+#include <HLRBRep_HLRToShape.hxx>
+#include <IntCurvesFace_ShapeIntersector.hxx>
+#include <Precision.hxx>
+#include <TopoDS_Edge.hxx>
+#include <TopoDS_Shape.hxx>
+#include <TopoDS_Vertex.hxx>
+#include <TopoDS_Wire.hxx>
+#include <TopoDS.hxx>
+#include <TopoDS_Iterator.hxx>
+#include <TopExp.hxx>
+#include <TopTools_ListIteratorOfListOfShape.hxx>
+#include <TopTools_MapOfShape.hxx>
+#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
+#include <TopTools_DataMapOfShapeReal.hxx>
+
+HYDROData_Make3dMesh::HYDROData_Make3dMesh( const TopoDS_Shape& aShape,
+ const Standard_Real Tolerance )
+{
+ myIntersector.Load(aShape, Tolerance);
+}
+
+Standard_Boolean HYDROData_Make3dMesh::GetHighestOriginal(const Standard_Real aX,
+ const Standard_Real aY,
+ gp_Pnt& HighestPoint)
+{
+ gp_Pnt ProjPnt(aX, aY, 0.);
+ gp_Lin Ray(ProjPnt, -gp::DZ());
+ myIntersector.PerformNearest(Ray, -Precision::Infinite(), 0.);
+ if (!myIntersector.IsDone() || myIntersector.NbPnt() == 0)
+ return Standard_False;
+
+ HighestPoint = myIntersector.Pnt(1);
+ return Standard_True;
+}
+
+//=======================================================================
+//function : FindClosestDirection
+//purpose : auxiliary function
+//=======================================================================
+TopoDS_Edge HYDROData_Projection::FindClosestDirection( const TopoDS_Vertex& StartVertex,
+ const TopTools_ListOfShape& Candidates,
+ const gp_Vec& StartDir )
+{
+ Standard_Real MinAngle = M_PI;
+ TopoDS_Edge theEdge;
+
+ TopTools_ListIteratorOfListOfShape itl(Candidates);
+ for (; itl.More(); itl.Next())
+ {
+ TopoDS_Edge anEdge = TopoDS::Edge(itl.Value());
+ BRepAdaptor_Curve BAcurve(anEdge);
+ gp_Pnt aPnt, aPnt2;
+ gp_Vec aDir, aDir2;
+
+ Standard_Real Par, Par2 = 0.; //to avoid warning
+ Standard_Boolean ToReverse = Standard_False;
+
+ TopoDS_Vertex V1, V2;
+ TopExp::Vertices(anEdge, V1, V2);
+ if (StartVertex.IsSame(V1))
+ Par = 0.99*BAcurve.FirstParameter() + 0.01*BAcurve.LastParameter();
+ else
+ {
+ Par = 0.01*BAcurve.FirstParameter() + 0.99*BAcurve.LastParameter();
+ ToReverse = Standard_True;
+ }
+ if (V1.IsSame(V2))
+ {
+ Par2 = 0.01*BAcurve.FirstParameter() + 0.99*BAcurve.LastParameter();
+ }
+
+ BAcurve.D1(Par, aPnt, aDir);
+ if (ToReverse)
+ aDir.Reverse();
+
+ if (V1.IsSame(V2))
+ {
+ BAcurve.D1(Par2, aPnt2, aDir2);
+ aDir2.Reverse();
+ }
+
+ Standard_Real anAngle = StartDir.Angle(aDir);
+ if (anAngle < MinAngle)
+ {
+ MinAngle = anAngle;
+ theEdge = anEdge;
+ }
+
+ if (V1.IsSame(V2))
+ {
+ anAngle = StartDir.Angle(aDir2);
+ if (anAngle < MinAngle)
+ {
+ MinAngle = anAngle;
+ theEdge = anEdge;
+ }
+ }
+ }
+
+ return theEdge;
+}
+
+//=======================================================================
+//function : BuildOutWire
+//purpose : auxiliary function
+//=======================================================================
+TopoDS_Wire HYDROData_Projection::BuildOutWire( const TopTools_IndexedDataMapOfShapeListOfShape& VEmap,
+ const TopoDS_Vertex& StartVertex,
+ TopoDS_Edge& StartEdge)
+{
+ Standard_Real AngularTol = 0.1; //0.01; //1.e-4; //Precision::Angular();
+ TopTools_MapOfShape BoundEdges;
+
+ TopoDS_Wire theWire;
+ BRep_Builder BB;
+ BB.MakeWire(theWire);
+
+ TopoDS_Vertex V1, V2;
+ TopExp::Vertices(StartEdge, V1, V2);
+ if (StartVertex.IsSame(V1))
+ StartEdge.Orientation(TopAbs_FORWARD);
+ else
+ StartEdge.Orientation(TopAbs_REVERSED);
+ BB.Add(theWire, StartEdge);
+ BoundEdges.Add(StartEdge);
+
+ TopoDS_Vertex CurVertex = (StartVertex.IsSame(V1))? V2 : V1;
+ TopoDS_Edge CurEdge = StartEdge;
+ gp_Vec Normal(0., 0., 1.);
+ for (;;)
+ {
+ if (CurVertex.IsSame(StartVertex))
+ {
+ theWire.Closed(Standard_True);
+ break;
+ }
+
+ const TopTools_ListOfShape& Candidates = VEmap.FindFromKey(CurVertex);
+ Standard_Real MinAngle = M_PI;
+
+ BRepAdaptor_Curve CurCurve(CurEdge);
+ TopExp::Vertices(CurEdge, V1, V2);
+ Standard_Real CurPar;
+ if (CurVertex.IsSame(V2))
+ CurPar = CurCurve.LastParameter();
+ else
+ CurPar = CurCurve.FirstParameter();
+ gp_Pnt aPnt;
+ gp_Vec CurDir;
+ CurCurve.D1(CurPar, aPnt, CurDir);
+ if (CurDir.SquareMagnitude() < Precision::PConfusion())
+ {
+ CurPar = (CurVertex.IsSame(V2))?
+ 0.01*CurCurve.FirstParameter() + 0.99*CurCurve.LastParameter() :
+ 0.99*CurCurve.FirstParameter() + 0.01*CurCurve.LastParameter();
+ CurCurve.D1(CurPar, aPnt, CurDir);
+ }
+ if (CurVertex.IsSame(V1))
+ CurDir.Reverse();
+
+ TopoDS_Edge theEdge;
+ TopTools_ListIteratorOfListOfShape itl(Candidates);
+ for (; itl.More(); itl.Next())
+ {
+ TopoDS_Edge anEdge = TopoDS::Edge(itl.Value());
+ if (BoundEdges.Contains(anEdge)) //if (anEdge.IsSame(CurEdge))
+ continue;
+
+ TopExp::Vertices(anEdge, V1, V2);
+ if (V1.IsSame(V2))
+ continue;
+
+ BRepAdaptor_Curve BAcurve(anEdge);
+ gp_Vec aDir;
+ Standard_Real aPar = (CurVertex.IsSame(V1))?
+ 0.99*BAcurve.FirstParameter() + 0.01*BAcurve.LastParameter() :
+ 0.01*BAcurve.FirstParameter() + 0.99*BAcurve.LastParameter();
+ //BAcurve.FirstParameter() : BAcurve.LastParameter();
+
+ BAcurve.D1(aPar, aPnt, aDir);
+ if (CurVertex.IsSame(V2))
+ aDir.Reverse();
+
+ Standard_Real anAngle = CurDir.AngleWithRef(aDir, Normal);
+ if (Abs(anAngle + M_PI) < AngularTol) //anAngle = -PI
+ continue;
+ if (anAngle < MinAngle)
+ {
+ MinAngle = anAngle;
+ theEdge = anEdge;
+ }
+ }
+ if (theEdge.IsNull())
+ break;
+
+ TopExp::Vertices(theEdge, V1, V2);
+ if (CurVertex.IsSame(V1))
+ theEdge.Orientation(TopAbs_FORWARD);
+ else
+ theEdge.Orientation(TopAbs_REVERSED);
+ BB.Add(theWire, theEdge);
+ BoundEdges.Add(theEdge);
+
+ CurVertex = (CurVertex.IsSame(V1))? V2 : V1;
+ CurEdge = theEdge;
+ }
+
+ return theWire;
+}
+
+//=======================================================================
+//Function : MakeProjection
+//purpose : this function makes the "shadow" of a shape on the plane XOY
+//=======================================================================
+TopoDS_Face HYDROData_Projection::MakeProjection( const TopoDS_Shape& aShape )
+{
+ HLRAlgo_Projector theProjector(gp::XOY());
+
+ Handle(HLRBRep_Algo) aHLRAlgo = new HLRBRep_Algo();
+ aHLRAlgo->Add(aShape);
+ aHLRAlgo->Projector(theProjector);
+ aHLRAlgo->Update();
+ aHLRAlgo->Hide();
+ HLRBRep_HLRToShape aHLRToShape(aHLRAlgo);
+
+ TopoDS_Shape SharpEdges, OutLines;
+ TopoDS_Compound Total;
+ BRep_Builder BB;
+ BB.MakeCompound(Total);
+
+ SharpEdges = aHLRToShape.VCompound();
+ OutLines = aHLRToShape.OutLineVCompound();
+
+ TopoDS_Iterator itc;
+ if (!SharpEdges.IsNull())
+ {
+ for (itc.Initialize(SharpEdges); itc.More(); itc.Next())
+ BB.Add(Total, itc.Value());
+ }
+ if (!OutLines.IsNull())
+ {
+ for (itc.Initialize(OutLines); itc.More(); itc.Next())
+ BB.Add(Total, itc.Value());
+ }
+
+ BRepBuilderAPI_Sewing aSewing;
+ Standard_Real tol = 1.0e-06;
+ Standard_Boolean NonManifoldMode = Standard_False;
+ aSewing.Init(tol, Standard_True,Standard_True,Standard_True,NonManifoldMode);
+ aSewing.SetFloatingEdgesMode(Standard_True);
+
+ aSewing.Add( Total );
+ aSewing.Perform();
+
+ TopoDS_Shape SewedEdges = aSewing.SewedShape();
+
+ BRepLib::BuildCurves3d( SewedEdges );
+
+ Bnd_Box theBox;
+ BRepBndLib::Add(SewedEdges, theBox);
+ Standard_Real Xmin, Ymin, Zmin, Xmax, Ymax, Zmax;
+ theBox.Get(Xmin, Ymin, Zmin, Xmax, Ymax, Zmax);
+
+ gp_Pnt P1(Xmin, Ymin, 0.), P2(Xmax, Ymin, 0.);
+ TopoDS_Edge LowerBound = BRepLib_MakeEdge(P1, P2);
+
+ Standard_Real Deviation = 1.e-7; //1.e-5;
+ BRepExtrema_DistShapeShape DSS(SewedEdges, LowerBound, Deviation);
+
+ TopTools_IndexedDataMapOfShapeListOfShape StartShapes;
+ TopTools_DataMapOfShapeReal EdgesWithPars;
+ Standard_Integer i;
+ for (i = 1; i <= DSS.NbSolution(); i++)
+ {
+ if (!StartShapes.Contains( DSS.SupportOnShape1(i) ))
+ {
+ TopTools_ListOfShape aList;
+ aList.Append( DSS.SupportOnShape2(i) );
+ StartShapes.Add( DSS.SupportOnShape1(i), aList );
+ }
+ else
+ {
+ TopTools_ListOfShape& aList = StartShapes.ChangeFromKey( DSS.SupportOnShape1(i) );
+ aList.Append( DSS.SupportOnShape2(i) );
+ }
+ if (DSS.SupportTypeShape1(i) == BRepExtrema_IsOnEdge)
+ {
+ Standard_Real aPar;
+ DSS.ParOnEdgeS1(i, aPar);
+ EdgesWithPars.Bind( DSS.SupportOnShape1(i), aPar );
+ }
+ }
+
+ TopoDS_Shape aStartShape;
+ for (i = 1; i <= StartShapes.Extent(); i++)
+ {
+ const TopoDS_Shape& aShape = StartShapes.FindKey(i);
+ if (aShape.ShapeType() == TopAbs_EDGE)
+ {
+ aStartShape = aShape;
+ break;
+ }
+ }
+ if (aStartShape.IsNull())
+ aStartShape = StartShapes.FindKey(1); //it is a vertex
+
+ TopoDS_Vertex StartVertex;
+ TopoDS_Edge StartEdge;
+ gp_Vec StartDir(1.,0.,0.);
+ TopTools_IndexedDataMapOfShapeListOfShape VEmap;
+ TopExp::MapShapesAndAncestors(SewedEdges, TopAbs_VERTEX, TopAbs_EDGE, VEmap);
+ if (aStartShape.ShapeType() == TopAbs_EDGE)
+ {
+ StartEdge = TopoDS::Edge(aStartShape);
+ Standard_Real StartPar = EdgesWithPars(StartEdge);
+ BRepAdaptor_Curve BAcurve(StartEdge);
+ gp_Pnt aPnt;
+ gp_Vec aDir;
+ BAcurve.D1(StartPar, aPnt, aDir);
+ StartVertex = (StartDir * aDir > 0.)?
+ TopExp::FirstVertex(StartEdge) : TopExp::LastVertex(StartEdge);
+ }
+ else // it is a vertex
+ {
+ StartVertex = TopoDS::Vertex(aStartShape);
+ const TopTools_ListOfShape& Candidates = VEmap.FindFromKey(StartVertex);
+ StartEdge = FindClosestDirection(StartVertex, Candidates, StartDir);
+ }
+
+ TopoDS_Wire OutWire = BuildOutWire(VEmap, StartVertex, StartEdge);
+ TopoDS_Face ProjFace = BRepLib_MakeFace(OutWire, Standard_True); //only plane
+
+ return ProjFace;
+}
+