1 // Copyright (C) 2007-2016 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
22 // File: GEOMAlgo_GetInPlaceAPI.cxx
24 // Author: Sergey KHROMOV
27 #include <GEOMAlgo_GetInPlaceAPI.hxx>
28 #include <GEOMAlgo_GetInPlace.hxx>
29 #include <GEOM_Object.hxx>
30 #include <GEOMUtils.hxx>
32 #include <Bnd_Box.hxx>
33 #include <BRepAdaptor_Surface.hxx>
34 #include <BRepBndLib.hxx>
35 #include <BRepBuilderAPI_MakeVertex.hxx>
36 #include <BRepExtrema_DistShapeShape.hxx>
37 #include <BRepGProp.hxx>
38 #include <BRep_Tool.hxx>
39 #include <Geom2d_Curve.hxx>
40 #include <GProp_GProps.hxx>
42 #include <Precision.hxx>
43 #include <TDataStd_IntegerArray.hxx>
45 #include <TopExp_Explorer.hxx>
47 #include <TopoDS_Vertex.hxx>
49 //=======================================================================
50 //function : GetInPlace
52 //=======================================================================
53 Standard_Boolean GEOMAlgo_GetInPlaceAPI::GetInPlace
54 (const TopoDS_Shape &theWhere,
55 const TopoDS_Shape &theWhat,
56 GEOMAlgo_GetInPlace &theGIP)
58 if (theWhere.IsNull() || theWhat.IsNull()) {
59 return Standard_False;
62 // Compute confusion tolerance.
63 Standard_Real aTolConf = Precision::Confusion();
66 for (i = 0; i < 2; ++i) {
67 TopExp_Explorer anExp(i == 0 ? theWhere : theWhat, TopAbs_VERTEX);
69 for (; anExp.More(); anExp.Next()) {
70 const TopoDS_Vertex aVtx = TopoDS::Vertex(anExp.Current());
71 const Standard_Real aTolVtx = BRep_Tool::Tolerance(aVtx);
73 if (aTolVtx > aTolConf) {
79 // Compute mass tolerance.
81 Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
82 Standard_Real aMassTol;
84 BRepBndLib::Add(theWhere, aBoundingBox);
85 BRepBndLib::Add(theWhat, aBoundingBox);
86 aBoundingBox.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
87 aMassTol = Max(aXmax - aXmin, aYmax - aYmin);
88 aMassTol = Max(aMassTol, aZmax - aZmin);
91 // Searching for the sub-shapes inside the ShapeWhere shape
92 theGIP.SetTolerance(aTolConf);
93 theGIP.SetTolMass(aMassTol);
94 theGIP.SetTolCG(aTolConf);
96 theGIP.SetArgument(theWhat);
97 theGIP.SetShapeWhere(theWhere);
101 int iErr = theGIP.ErrorStatus();
104 return Standard_False;
107 return Standard_True;
110 //=======================================================================
111 //function : GetInPlaceOld
113 //=======================================================================
114 Standard_Integer GEOMAlgo_GetInPlaceAPI::GetInPlaceOld
115 (const TopoDS_Shape &theWhere,
116 const TopoDS_Shape &theWhat,
117 TopTools_ListOfShape &theShapesInPlace)
119 theShapesInPlace.Clear();
121 if (theWhere.IsNull() || theWhat.IsNull()) {
122 // Error: aWhere and aWhat TopoDS_Shape are Null.
127 TopAbs_ShapeEnum iType = GEOMUtils::GetTypeOfSimplePart(theWhat);
129 if (iType == TopAbs_SHAPE) {
130 // Error: An attempt to extract a shape of not supported type.
134 // Compute confusion tolerance.
135 Standard_Real aTolConf = Precision::Confusion();
138 for (i = 0; i < 2; ++i) {
139 TopExp_Explorer anExp(i == 0 ? theWhere : theWhat, TopAbs_VERTEX);
141 for (; anExp.More(); anExp.Next()) {
142 const TopoDS_Vertex aVtx = TopoDS::Vertex(anExp.Current());
143 const Standard_Real aTolVtx = BRep_Tool::Tolerance(aVtx);
145 if (aTolVtx > aTolConf) {
151 // Compute mass tolerance.
152 Bnd_Box aBoundingBox;
153 Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
154 Standard_Real aMassTol;
156 BRepBndLib::Add(theWhere, aBoundingBox);
157 BRepBndLib::Add(theWhat, aBoundingBox);
158 aBoundingBox.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
159 aMassTol = Max(aXmax - aXmin, aYmax - aYmin);
160 aMassTol = Max(aMassTol, aZmax - aZmin);
161 aMassTol *= aTolConf;
163 // Compute the result.
164 TopExp_Explorer Exp_aWhat (theWhat, iType);
165 TopExp_Explorer Exp_aWhere (theWhere, iType);
166 Standard_Real tab_aWhat[4], tab_aWhere[4];
167 gp_Pnt aPnt, aPnt_aWhat;
168 TopoDS_Shape aPntShape;
169 TopoDS_Vertex aVertex;
170 bool isFound = false;
171 TopTools_MapOfShape map_aWhere;
173 for (; Exp_aWhere.More(); Exp_aWhere.Next()) {
174 if (!map_aWhere.Add(Exp_aWhere.Current()))
175 continue; // skip repeated shape to avoid mass addition
176 GetShapeProperties( Exp_aWhere.Current(), tab_aWhere, aPnt );
177 for ( Exp_aWhat.ReInit(); Exp_aWhat.More(); Exp_aWhat.Next() ) {
178 GetShapeProperties( Exp_aWhat.Current(), tab_aWhat, aPnt_aWhat );
179 if (fabs(tab_aWhat[3] - tab_aWhere[3]) <= aMassTol && aPnt_aWhat.Distance(aPnt) <= aTolConf)
182 if (tab_aWhat[3] > tab_aWhere[3]) {
183 aPntShape = BRepBuilderAPI_MakeVertex( aPnt ).Shape();
184 aVertex = TopoDS::Vertex( aPntShape );
185 BRepExtrema_DistShapeShape aWhereDistance ( aVertex, Exp_aWhere.Current() );
186 BRepExtrema_DistShapeShape aWhatDistance ( aVertex, Exp_aWhat.Current() );
187 if (aWhereDistance.IsDone() && aWhatDistance.IsDone() &&
188 fabs(aWhereDistance.Value() - aWhatDistance.Value()) <= aTolConf)
190 // 0020162: "EDF 961 GEOM : Getinplace is getting additional orthogonal faces"
191 // aVertex must be projected to the same point on Where and on What
192 gp_Pnt pOnWhat = aWhatDistance.PointOnShape2(1);
193 gp_Pnt pOnWhere = aWhereDistance.PointOnShape2(1);
194 isFound = (pOnWhat.Distance(pOnWhere) <= aTolConf);
195 if ( isFound && iType == TopAbs_FACE )
197 // check normals at pOnWhat and pOnWhere
198 const double angleTol = M_PI/180.;
199 gp_Vec normToWhat = GetNormal( TopoDS::Face(Exp_aWhat.Current()), aWhatDistance);
200 gp_Vec normToWhere = GetNormal( TopoDS::Face(Exp_aWhere.Current()), aWhereDistance);
201 if ( normToWhat * normToWhere < 0 )
202 normToWhat.Reverse();
203 isFound = ( normToWhat.Angle( normToWhere ) < angleTol );
209 theShapesInPlace.Append(Exp_aWhere.Current());
210 //aWhere_Mass += tab_aWhere[3];
217 if (theShapesInPlace.Extent() == 0) {
218 // Not found any Results
225 //=======================================================================
226 //function : GetNormal
228 //=======================================================================
229 gp_Vec GEOMAlgo_GetInPlaceAPI::GetNormal
230 (const TopoDS_Face &theFace,
231 const BRepExtrema_DistShapeShape &theExtrema)
233 gp_Vec defaultNorm(1,0,0); // to have same normals on different faces
235 // get UV at extrema point
236 Standard_Real u,v, f,l;
237 switch ( theExtrema.SupportTypeShape2(1) ) {
238 case BRepExtrema_IsInFace: {
239 theExtrema.ParOnFaceS2(1, u, v );
242 case BRepExtrema_IsOnEdge: {
243 TopoDS_Edge edge = TopoDS::Edge( theExtrema.SupportOnShape2(1));
244 Handle(Geom2d_Curve) pcurve =
245 BRep_Tool::CurveOnSurface(edge, theFace, f,l);
247 theExtrema.ParOnEdgeS2( 1, u );
248 gp_Pnt2d uv = pcurve->Value( u );
253 case BRepExtrema_IsVertex: return defaultNorm;
256 BRepAdaptor_Surface surface( theFace, false );
257 gp_Vec du, dv; gp_Pnt p;
258 surface.D1( u, v, p, du, dv );
262 } catch (Standard_Failure ) {
267 //=======================================================================
268 //function : GetShapeProperties
270 //=======================================================================
271 void GEOMAlgo_GetInPlaceAPI::GetShapeProperties(const TopoDS_Shape &theShape,
272 Standard_Real theTab[],
277 Standard_Real aShapeSize;
279 if (theShape.ShapeType() == TopAbs_VERTEX) {
280 aCenterMass = BRep_Tool::Pnt(TopoDS::Vertex(theShape));
281 } else if (theShape.ShapeType() == TopAbs_EDGE) {
282 BRepGProp::LinearProperties(theShape, aProps);
283 } else if (theShape.ShapeType() == TopAbs_FACE) {
284 BRepGProp::SurfaceProperties(theShape, aProps);
286 BRepGProp::VolumeProperties(theShape, aProps);
289 if (theShape.ShapeType() == TopAbs_VERTEX) {
292 aCenterMass = aProps.CentreOfMass();
293 aShapeSize = aProps.Mass();
296 theVertex = aCenterMass;
297 theTab[0] = theVertex.X();
298 theTab[1] = theVertex.Y();
299 theTab[2] = theVertex.Z();
300 theTab[3] = aShapeSize;
303 //=======================================================================
304 //function : GetInPlaceByHistory
306 //=======================================================================
307 Standard_Boolean GEOMAlgo_GetInPlaceAPI::GetInPlaceByHistory
308 (const Handle(GEOM_Function) &theWhereFunction,
309 const TopTools_IndexedMapOfShape &theWhereIndices,
310 const TopoDS_Shape &theWhat,
311 TopTools_ListOfShape &theShapesInPlace)
313 if (theWhereFunction.IsNull() || theWhat.IsNull())
314 return Standard_False;
316 if (theWhereIndices.Contains(theWhat)) {
317 // entity was not changed by the operation
318 theShapesInPlace.Append(theWhat);
320 return Standard_True;
323 // try to find in history
324 TDF_Label aHistoryLabel = theWhereFunction->GetHistoryEntry(Standard_False);
326 // search in history for all argument shapes
327 Standard_Boolean isFound = Standard_False;
328 Standard_Boolean isGood = Standard_False;
330 TDF_LabelSequence aLabelSeq;
331 theWhereFunction->GetDependency(aLabelSeq);
332 Standard_Integer nbArg = aLabelSeq.Length();
334 for (Standard_Integer iarg = 1; iarg <= nbArg && !isFound; iarg++) {
336 TDF_Label anArgumentRefLabel = aLabelSeq.Value(iarg);
338 Handle(GEOM_Object) anArgumentObject = GEOM_Object::GetReferencedObject(anArgumentRefLabel);
339 TopoDS_Shape anArgumentShape = anArgumentObject->GetValue();
341 TopTools_IndexedMapOfShape anArgumentIndices;
342 TopExp::MapShapes(anArgumentShape, anArgumentIndices);
344 if (anArgumentIndices.Contains(theWhat)) {
345 isFound = Standard_True;
346 Standard_Integer aWhatIndex = anArgumentIndices.FindIndex(theWhat);
348 // Find corresponding label in history
349 TDF_Label anArgumentHistoryLabel =
350 theWhereFunction->GetArgumentHistoryEntry(anArgumentRefLabel, Standard_False);
351 if (anArgumentHistoryLabel.IsNull()) {
352 // Lost History of operation argument. Possibly, all its entities was removed.
353 isGood = Standard_True;
356 TDF_Label aWhatHistoryLabel = anArgumentHistoryLabel.FindChild(aWhatIndex, Standard_False);
358 if (aWhatHistoryLabel.IsNull()) {
359 // Removed entity ? Compound ? Compsolid ? Shell ? Wire
360 isGood = Standard_False;
362 Handle(TDataStd_IntegerArray) anIntegerArray;
363 if (!aWhatHistoryLabel.FindAttribute(TDataStd_IntegerArray::GetID(), anIntegerArray)) {
364 //Error: Empty modifications history for the sought shape.
365 isGood = Standard_False;
368 isGood = Standard_True;
369 Standard_Integer imod, aModifLen = anIntegerArray->Array()->Length();
370 for (imod = 1; imod <= aModifLen; imod++) {
371 const Standard_Integer anIndex =
372 anIntegerArray->Array()->Value(imod);
374 theShapesInPlace.Append(theWhereIndices.FindKey(anIndex));
385 // try compound/compsolid/shell/wire element by element
386 Standard_Boolean isFoundAny = Standard_False;
387 TopTools_MapOfShape mapShape;
389 if (theWhat.ShapeType() == TopAbs_COMPOUND ||
390 theWhat.ShapeType() == TopAbs_COMPSOLID) {
391 // recursive processing of compound/compsolid
392 TopoDS_Iterator anIt (theWhat, Standard_True, Standard_True);
393 for (; anIt.More(); anIt.Next()) {
394 if (mapShape.Add(anIt.Value())) {
395 TopoDS_Shape curWhat = anIt.Value();
396 isFoundAny = GetInPlaceByHistory(theWhereFunction, theWhereIndices, curWhat, theShapesInPlace);
397 if (isFoundAny) isFound = Standard_True;
401 else if (theWhat.ShapeType() == TopAbs_SHELL) {
402 // try to replace a shell by its faces images
403 TopExp_Explorer anExp (theWhat, TopAbs_FACE);
404 for (; anExp.More(); anExp.Next()) {
405 if (mapShape.Add(anExp.Current())) {
406 TopoDS_Shape curWhat = anExp.Current();
407 isFoundAny = GetInPlaceByHistory(theWhereFunction, theWhereIndices, curWhat, theShapesInPlace);
408 if (isFoundAny) isFound = Standard_True;
412 else if (theWhat.ShapeType() == TopAbs_WIRE) {
413 // try to replace a wire by its edges images
414 TopExp_Explorer anExp (theWhat, TopAbs_EDGE);
415 for (; anExp.More(); anExp.Next()) {
416 if (mapShape.Add(anExp.Current())) {
417 TopoDS_Shape curWhat = anExp.Current();
418 isFoundAny = GetInPlaceByHistory(theWhereFunction, theWhereIndices, curWhat, theShapesInPlace);
419 if (isFoundAny) isFound = Standard_True;