1 // Created on: 1995-03-08
2 // Created by: Bruno DUMORTIER
3 // Copyright (c) 1995-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
6 // This file is part of Open CASCADE Technology software library.
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
18 #include <BRep_Builder.hxx>
19 #include <BRep_Tool.hxx>
20 #include <BRepBuilderAPI_MakeVertex.hxx>
21 #include <BRepExtrema_DistShapeShape.hxx>
22 #include <BRepLProp_SLProps.hxx>
23 #include <BRepPrimAPI_MakeHalfSpace.hxx>
27 #include <StdFail_NotDone.hxx>
28 #include <TopExp_Explorer.hxx>
30 #include <TopoDS_Face.hxx>
31 #include <TopoDS_Shell.hxx>
32 #include <TopoDS_Solid.hxx>
33 #include <TopoDS_Vertex.hxx>
35 //=======================================================================
36 //function : getNormalOnFace
38 //=======================================================================
40 static gp_Dir getNormalOnFace(const TopoDS_Face& theFace,
41 const Standard_Real theU,
42 const Standard_Real theV)
44 Standard_Real aPrec = gp::Resolution();
45 BRepLProp_SLProps aProps(BRepAdaptor_Surface(theFace), theU, theV, 2, aPrec);
46 gp_Dir aNormal = aProps.Normal();
47 if (theFace.Orientation() == TopAbs_REVERSED)
52 //=======================================================================
53 //function : getNormalFromEdge
54 //purpose : Get average normal at the point with the given parameter on the edge
55 //=======================================================================
57 static Standard_Boolean getNormalFromEdge(const TopoDS_Shape& theShape,
58 const TopoDS_Edge& theEdge,
59 const Standard_Real thePar,
63 TopExp_Explorer ex(theShape, TopAbs_FACE);
64 for (; ex.More(); ex.Next()) {
65 const TopoDS_Face& aF = TopoDS::Face(ex.Current());
66 TopExp_Explorer ex1(aF, TopAbs_EDGE);
67 for (; ex1.More(); ex1.Next()) {
68 if (ex1.Current().IsSame(theEdge)) {
70 Handle(Geom2d_Curve) aC2d = BRep_Tool::CurveOnSurface(theEdge, aF, f, l);
71 gp_Pnt2d aP2d = aC2d->Value(thePar);
72 gp_Dir aNorm = getNormalOnFace(aF, aP2d.X(), aP2d.Y());
77 if (aSum.SquareModulus() > gp::Resolution()) {
81 return Standard_False;
84 //=======================================================================
85 //function : getNormalFromVertex
86 //purpose : Get average normal at the point of the vertex
87 //=======================================================================
89 static Standard_Boolean getNormalFromVertex(const TopoDS_Shape& theShape,
90 const TopoDS_Vertex& theVer,
94 TopExp_Explorer ex(theShape, TopAbs_FACE);
95 for (; ex.More(); ex.Next()) {
96 const TopoDS_Face& aF = TopoDS::Face(ex.Current());
97 TopExp_Explorer ex1(aF, TopAbs_VERTEX);
98 for (; ex1.More(); ex1.Next()) {
99 if (ex1.Current().IsSame(theVer)) {
100 gp_Pnt2d aP2d = BRep_Tool::Parameters(theVer, aF);
101 gp_Dir aNorm = getNormalOnFace(aF, aP2d.X(), aP2d.Y());
106 if (aSum.SquareModulus() > gp::Resolution()) {
108 return Standard_True;
110 return Standard_False;
113 //=======================================================================
114 //function : FindExtrema
115 //purpose : This finction is called to find the nearest normal projection
116 // of a point <aPnt> on a shape <aShape>.
117 // 1) return true if extrema is found.
119 // - theMinPnt : The solution point
120 // - theNormal : The normal direction to the shape at projection point
121 //=======================================================================
122 static Standard_Boolean FindExtrema(const gp_Pnt& thePnt,
123 const TopoDS_Shape& theShape,
127 TopoDS_Vertex aRefVertex = BRepBuilderAPI_MakeVertex(thePnt);
129 BRepExtrema_DistShapeShape ext(aRefVertex, theShape);
131 if (!ext.IsDone() || ext.NbSolution() == 0)
132 return Standard_False;
134 // the point projection exist
135 Standard_Integer nbext = ext.NbSolution();
136 // try to find a projection on face
137 for (Standard_Integer iext = 1; iext <= nbext; iext++) {
138 if (ext.SupportTypeShape2(iext) == BRepExtrema_IsInFace) {
139 TopoDS_Face aF = TopoDS::Face(ext.SupportOnShape2(iext));
140 theMinPnt = ext.PointOnShape2(iext);
141 Standard_Real aU, aV;
142 ext.ParOnFaceS2(iext, aU, aV);
143 theNormal = getNormalOnFace(aF, aU, aV);
144 return Standard_True;
148 // if not found then take any edge or vertex solution
149 for (Standard_Integer iext = 1; iext <= nbext; iext++) {
150 if (ext.SupportTypeShape2(iext) == BRepExtrema_IsOnEdge) {
151 theMinPnt = ext.PointOnShape2(iext);
153 ext.ParOnEdgeS2(iext, aPar);
154 TopoDS_Edge aE = TopoDS::Edge(ext.SupportOnShape2(iext));
155 if (getNormalFromEdge(theShape, aE, aPar, theNormal))
156 return Standard_True;
158 else if (ext.SupportTypeShape2(iext) == BRepExtrema_IsVertex) {
159 theMinPnt = ext.PointOnShape2(iext);
160 TopoDS_Vertex aV = TopoDS::Vertex(ext.SupportOnShape2(iext));
161 if (getNormalFromVertex(theShape, aV, theNormal))
162 return Standard_True;
165 return Standard_False;
168 //=======================================================================
169 //function : isOutside
171 //=======================================================================
173 static Standard_Boolean isOutside(const gp_Pnt& thePnt,
174 const gp_Pnt& thePonF,
175 const gp_Dir& theNormal)
177 gp_Dir anOppRef(thePnt.XYZ() - thePonF.XYZ());
178 Standard_Real aSca = theNormal * anOppRef;
179 // outside if same directions
183 //=======================================================================
184 //function : BRepPrimAPI_MakeHalfSpace
186 //=======================================================================
188 BRepPrimAPI_MakeHalfSpace::BRepPrimAPI_MakeHalfSpace(const TopoDS_Face& theFace,
189 const gp_Pnt& theRefPnt)
191 // Set the flag is <IsDone> to False.
198 if (FindExtrema(theRefPnt, theFace, aMinPnt, aNormal)) {
199 Standard_Boolean toReverse = isOutside(theRefPnt, aMinPnt, aNormal);
201 // Construction of the open solid.
202 BRep_Builder().MakeShell(aShell);
203 BRep_Builder().Add(aShell, theFace);
204 BRep_Builder().MakeSolid(mySolid);
208 BRep_Builder().Add(mySolid, aShell);
215 //=======================================================================
216 //function : BRepPrimAPI_MakeHalfSpace
218 //=======================================================================
220 BRepPrimAPI_MakeHalfSpace::BRepPrimAPI_MakeHalfSpace(const TopoDS_Shell& theShell,
221 const gp_Pnt& theRefPnt)
223 // Set the flag is <IsDone> to False.
226 // Find the point of the skin closest to the reference point.
229 if (FindExtrema(theRefPnt, theShell, aMinPnt, aNormal)) {
230 Standard_Boolean toReverse = isOutside(theRefPnt, aMinPnt, aNormal);
232 // Construction of the open solid.
233 TopoDS_Shell aShell = theShell;
234 BRep_Builder().MakeSolid(mySolid);
238 BRep_Builder().Add(mySolid, aShell);
245 //=======================================================================
248 //=======================================================================
250 const TopoDS_Solid& BRepPrimAPI_MakeHalfSpace::Solid() const
252 StdFail_NotDone_Raise_if( !IsDone(), "BRepPrimAPI_MakeHalfSpace::Solid");
258 //=======================================================================
259 //function : TopoDS_Solid
261 //=======================================================================
263 BRepPrimAPI_MakeHalfSpace::operator TopoDS_Solid() const