0031687: Draw Harness, ViewerTest - extend command vrenderparams with option updating...
[occt.git] / src / BRepPrimAPI / BRepPrimAPI_MakeHalfSpace.cxx
CommitLineData
b311480e 1// Created on: 1995-03-08
2// Created by: Bruno DUMORTIER
3// Copyright (c) 1995-1999 Matra Datavision
973c2be1 4// Copyright (c) 1999-2014 OPEN CASCADE SAS
b311480e 5//
973c2be1 6// This file is part of Open CASCADE Technology software library.
b311480e 7//
d5f74e42 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
973c2be1 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.
b311480e 13//
973c2be1 14// Alternatively, this file may be used under the terms of Open CASCADE
15// commercial license or contractual agreement.
7fd59977 16
7fd59977 17
18#include <BRep_Builder.hxx>
42cf5bc1 19#include <BRep_Tool.hxx>
7fd59977 20#include <BRepBuilderAPI_MakeVertex.hxx>
e57aedeb 21#include <BRepExtrema_DistShapeShape.hxx>
7fd59977 22#include <BRepLProp_SLProps.hxx>
42cf5bc1 23#include <BRepPrimAPI_MakeHalfSpace.hxx>
7fd59977 24#include <gp.hxx>
25#include <gp_Dir.hxx>
42cf5bc1 26#include <gp_Pnt.hxx>
27#include <StdFail_NotDone.hxx>
7fd59977 28#include <TopExp_Explorer.hxx>
29#include <TopoDS.hxx>
42cf5bc1 30#include <TopoDS_Face.hxx>
31#include <TopoDS_Shell.hxx>
32#include <TopoDS_Solid.hxx>
7fd59977 33#include <TopoDS_Vertex.hxx>
7fd59977 34
35//=======================================================================
e57aedeb 36//function : getNormalOnFace
37//purpose :
38//=======================================================================
39
40static gp_Dir getNormalOnFace(const TopoDS_Face& theFace,
41 const Standard_Real theU,
42 const Standard_Real theV)
7fd59977 43{
e57aedeb 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)
48 aNormal.Reverse();
49 return aNormal;
50}
51
52//=======================================================================
53//function : getNormalFromEdge
54//purpose : Get average normal at the point with the given parameter on the edge
55//=======================================================================
56
57static Standard_Boolean getNormalFromEdge(const TopoDS_Shape& theShape,
58 const TopoDS_Edge& theEdge,
59 const Standard_Real thePar,
60 gp_Dir& theNormal)
61{
62 gp_XYZ aSum;
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)) {
69 Standard_Real f, l;
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());
73 aSum += aNorm.XYZ();
7fd59977 74 }
75 }
e57aedeb 76 }
77 if (aSum.SquareModulus() > gp::Resolution()) {
78 theNormal = aSum;
79 return Standard_True;
80 }
81 return Standard_False;
82}
83
84//=======================================================================
85//function : getNormalFromVertex
86//purpose : Get average normal at the point of the vertex
87//=======================================================================
88
89static Standard_Boolean getNormalFromVertex(const TopoDS_Shape& theShape,
90 const TopoDS_Vertex& theVer,
91 gp_Dir& theNormal)
92{
93 gp_XYZ aSum;
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());
102 aSum += aNorm.XYZ();
7fd59977 103 }
104 }
e57aedeb 105 }
106 if (aSum.SquareModulus() > gp::Resolution()) {
107 theNormal = aSum;
7fd59977 108 return Standard_True;
109 }
e57aedeb 110 return Standard_False;
111}
7fd59977 112
e57aedeb 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.
118// 2) Set in:
119// - theMinPnt : The solution point
120// - theNormal : The normal direction to the shape at projection point
121//=======================================================================
122static Standard_Boolean FindExtrema(const gp_Pnt& thePnt,
123 const TopoDS_Shape& theShape,
124 gp_Pnt& theMinPnt,
125 gp_Dir& theNormal)
126{
127 TopoDS_Vertex aRefVertex = BRepBuilderAPI_MakeVertex(thePnt);
128
129 BRepExtrema_DistShapeShape ext(aRefVertex, theShape);
130
131 if (!ext.IsDone() || ext.NbSolution() == 0)
132 return Standard_False;
7fd59977 133
e57aedeb 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;
145 }
146 }
147
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);
152 Standard_Real aPar;
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;
157 }
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;
163 }
164 }
165 return Standard_False;
7fd59977 166}
167
e57aedeb 168//=======================================================================
169//function : isOutside
170//purpose :
171//=======================================================================
7fd59977 172
e57aedeb 173static Standard_Boolean isOutside(const gp_Pnt& thePnt,
174 const gp_Pnt& thePonF,
175 const gp_Dir& theNormal)
176{
177 gp_Dir anOppRef(thePnt.XYZ() - thePonF.XYZ());
178 Standard_Real aSca = theNormal * anOppRef;
179 // outside if same directions
180 return aSca > 0.;
181}
7fd59977 182
183//=======================================================================
184//function : BRepPrimAPI_MakeHalfSpace
185//purpose :
186//=======================================================================
187
e57aedeb 188BRepPrimAPI_MakeHalfSpace::BRepPrimAPI_MakeHalfSpace(const TopoDS_Face& theFace,
189 const gp_Pnt& theRefPnt)
7fd59977 190{
191 // Set the flag is <IsDone> to False.
192 NotDone();
193
e57aedeb 194 TopoDS_Shell aShell;
195
196 gp_Pnt aMinPnt;
197 gp_Dir aNormal;
198 if (FindExtrema(theRefPnt, theFace, aMinPnt, aNormal)) {
199 Standard_Boolean toReverse = isOutside(theRefPnt, aMinPnt, aNormal);
200
0d969553 201 // Construction of the open solid.
e57aedeb 202 BRep_Builder().MakeShell(aShell);
203 BRep_Builder().Add(aShell, theFace);
204 BRep_Builder().MakeSolid(mySolid);
205 if (toReverse) {
206 aShell.Reverse();
7fd59977 207 }
e57aedeb 208 BRep_Builder().Add(mySolid, aShell);
288fff89 209 myShape = mySolid;
7fd59977 210 Done();
211 }
212}
213
214
215//=======================================================================
216//function : BRepPrimAPI_MakeHalfSpace
217//purpose :
218//=======================================================================
219
e57aedeb 220BRepPrimAPI_MakeHalfSpace::BRepPrimAPI_MakeHalfSpace(const TopoDS_Shell& theShell,
221 const gp_Pnt& theRefPnt)
7fd59977 222{
223 // Set the flag is <IsDone> to False.
224 NotDone();
225
0d969553 226 // Find the point of the skin closest to the reference point.
e57aedeb 227 gp_Pnt aMinPnt;
228 gp_Dir aNormal;
229 if (FindExtrema(theRefPnt, theShell, aMinPnt, aNormal)) {
230 Standard_Boolean toReverse = isOutside(theRefPnt, aMinPnt, aNormal);
7fd59977 231
0d969553 232 // Construction of the open solid.
e57aedeb 233 TopoDS_Shell aShell = theShell;
234 BRep_Builder().MakeSolid(mySolid);
235 if (toReverse) {
7fd59977 236 aShell.Reverse();
237 }
e57aedeb 238 BRep_Builder().Add(mySolid, aShell);
288fff89 239 myShape = mySolid;
7fd59977 240 Done();
241 }
242}
243
244
245//=======================================================================
246//function : Solid
247//purpose :
248//=======================================================================
249
250const TopoDS_Solid& BRepPrimAPI_MakeHalfSpace::Solid() const
251{
252 StdFail_NotDone_Raise_if( !IsDone(), "BRepPrimAPI_MakeHalfSpace::Solid");
253 return mySolid;
254}
255
256
257
258//=======================================================================
259//function : TopoDS_Solid
260//purpose :
261//=======================================================================
262
263BRepPrimAPI_MakeHalfSpace::operator TopoDS_Solid() const
264{
265 return Solid();
266}