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>
48 #include <TColStd_MapOfInteger.hxx>
50 //=======================================================================
51 //function : GetInPlace
53 //=======================================================================
54 Standard_Boolean GEOMAlgo_GetInPlaceAPI::GetInPlace
55 (const TopoDS_Shape &theWhere,
56 const TopoDS_Shape &theWhat,
57 GEOMAlgo_GetInPlace &theGIP)
59 if (theWhere.IsNull() || theWhat.IsNull()) {
60 return Standard_False;
63 // Compute confusion tolerance.
64 Standard_Real aTolConf = Precision::Confusion();
67 for (i = 0; i < 2; ++i) {
68 TopExp_Explorer anExp(i == 0 ? theWhere : theWhat, TopAbs_VERTEX);
70 for (; anExp.More(); anExp.Next()) {
71 const TopoDS_Vertex aVtx = TopoDS::Vertex(anExp.Current());
72 const Standard_Real aTolVtx = BRep_Tool::Tolerance(aVtx);
74 if (aTolVtx > aTolConf) {
80 // Compute mass tolerance.
82 Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
83 Standard_Real aMassTol;
85 BRepBndLib::Add(theWhere, aBoundingBox);
86 BRepBndLib::Add(theWhat, aBoundingBox);
87 aBoundingBox.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
88 aMassTol = Max(aXmax - aXmin, aYmax - aYmin);
89 aMassTol = Max(aMassTol, aZmax - aZmin);
92 // Searching for the sub-shapes inside the ShapeWhere shape
93 theGIP.SetTolerance(aTolConf);
94 theGIP.SetTolMass(aMassTol);
95 theGIP.SetTolCG(aTolConf);
97 theGIP.SetArgument(theWhat);
98 theGIP.SetShapeWhere(theWhere);
102 int iErr = theGIP.ErrorStatus();
105 return Standard_False;
108 return Standard_True;
111 //=======================================================================
112 //function : GetInPlaceOld
114 //=======================================================================
115 Standard_Integer GEOMAlgo_GetInPlaceAPI::GetInPlaceOld
116 (const TopoDS_Shape &theWhere,
117 const TopoDS_Shape &theWhat,
118 TopTools_ListOfShape &theShapesInPlace)
120 theShapesInPlace.Clear();
122 if (theWhere.IsNull() || theWhat.IsNull()) {
123 // Error: aWhere and aWhat TopoDS_Shape are Null.
128 TopAbs_ShapeEnum iType = GEOMUtils::GetTypeOfSimplePart(theWhat);
130 if (iType == TopAbs_SHAPE) {
131 // Error: An attempt to extract a shape of not supported type.
135 // Compute confusion tolerance.
136 Standard_Real aTolConf = Precision::Confusion();
139 for (i = 0; i < 2; ++i) {
140 TopExp_Explorer anExp(i == 0 ? theWhere : theWhat, TopAbs_VERTEX);
142 for (; anExp.More(); anExp.Next()) {
143 const TopoDS_Vertex aVtx = TopoDS::Vertex(anExp.Current());
144 const Standard_Real aTolVtx = BRep_Tool::Tolerance(aVtx);
146 if (aTolVtx > aTolConf) {
152 // Compute mass tolerance.
153 Bnd_Box aBoundingBox;
154 Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
155 Standard_Real aMassTol;
157 BRepBndLib::Add(theWhere, aBoundingBox);
158 BRepBndLib::Add(theWhat, aBoundingBox);
159 aBoundingBox.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
160 aMassTol = Max(aXmax - aXmin, aYmax - aYmin);
161 aMassTol = Max(aMassTol, aZmax - aZmin);
162 aMassTol *= aTolConf;
164 // Compute the result.
165 TopExp_Explorer Exp_aWhat (theWhat, iType);
166 TopExp_Explorer Exp_aWhere (theWhere, iType);
167 Standard_Real tab_aWhat[4], tab_aWhere[4];
168 gp_Pnt aPnt, aPnt_aWhat;
169 TopoDS_Shape aPntShape;
170 TopoDS_Vertex aVertex;
171 bool isFound = false;
172 TopTools_MapOfShape map_aWhere;
174 for (; Exp_aWhere.More(); Exp_aWhere.Next()) {
175 if (!map_aWhere.Add(Exp_aWhere.Current()))
176 continue; // skip repeated shape to avoid mass addition
177 GetShapeProperties( Exp_aWhere.Current(), tab_aWhere, aPnt );
178 for ( Exp_aWhat.ReInit(); Exp_aWhat.More(); Exp_aWhat.Next() ) {
179 GetShapeProperties( Exp_aWhat.Current(), tab_aWhat, aPnt_aWhat );
180 if (fabs(tab_aWhat[3] - tab_aWhere[3]) <= aMassTol && aPnt_aWhat.Distance(aPnt) <= aTolConf)
183 if (tab_aWhat[3] > tab_aWhere[3]) {
184 aPntShape = BRepBuilderAPI_MakeVertex( aPnt ).Shape();
185 aVertex = TopoDS::Vertex( aPntShape );
186 BRepExtrema_DistShapeShape aWhereDistance ( aVertex, Exp_aWhere.Current() );
187 BRepExtrema_DistShapeShape aWhatDistance ( aVertex, Exp_aWhat.Current() );
188 if (aWhereDistance.IsDone() && aWhatDistance.IsDone() &&
189 fabs(aWhereDistance.Value() - aWhatDistance.Value()) <= aTolConf)
191 // 0020162: "EDF 961 GEOM : Getinplace is getting additional orthogonal faces"
192 // aVertex must be projected to the same point on Where and on What
193 gp_Pnt pOnWhat = aWhatDistance.PointOnShape2(1);
194 gp_Pnt pOnWhere = aWhereDistance.PointOnShape2(1);
195 isFound = (pOnWhat.Distance(pOnWhere) <= aTolConf);
196 if ( isFound && iType == TopAbs_FACE )
198 // check normals at pOnWhat and pOnWhere
199 const double angleTol = M_PI/180.;
200 gp_Vec normToWhat = GetNormal( TopoDS::Face(Exp_aWhat.Current()), aWhatDistance);
201 gp_Vec normToWhere = GetNormal( TopoDS::Face(Exp_aWhere.Current()), aWhereDistance);
202 if ( normToWhat * normToWhere < 0 )
203 normToWhat.Reverse();
204 isFound = ( normToWhat.Angle( normToWhere ) < angleTol );
210 theShapesInPlace.Append(Exp_aWhere.Current());
211 //aWhere_Mass += tab_aWhere[3];
218 if (theShapesInPlace.Extent() == 0) {
219 // Not found any Results
226 //=======================================================================
227 //function : GetNormal
229 //=======================================================================
230 gp_Vec GEOMAlgo_GetInPlaceAPI::GetNormal
231 (const TopoDS_Face &theFace,
232 const BRepExtrema_DistShapeShape &theExtrema)
234 gp_Vec defaultNorm(1,0,0); // to have same normals on different faces
236 // get UV at extrema point
237 Standard_Real u,v, f,l;
238 switch ( theExtrema.SupportTypeShape2(1) ) {
239 case BRepExtrema_IsInFace: {
240 theExtrema.ParOnFaceS2(1, u, v );
243 case BRepExtrema_IsOnEdge: {
244 TopoDS_Edge edge = TopoDS::Edge( theExtrema.SupportOnShape2(1));
245 Handle(Geom2d_Curve) pcurve =
246 BRep_Tool::CurveOnSurface(edge, theFace, f,l);
248 theExtrema.ParOnEdgeS2( 1, u );
249 gp_Pnt2d uv = pcurve->Value( u );
254 case BRepExtrema_IsVertex: return defaultNorm;
257 BRepAdaptor_Surface surface( theFace, false );
258 gp_Vec du, dv; gp_Pnt p;
259 surface.D1( u, v, p, du, dv );
263 } catch (Standard_Failure ) {
268 //=======================================================================
269 //function : GetShapeProperties
271 //=======================================================================
272 void GEOMAlgo_GetInPlaceAPI::GetShapeProperties(const TopoDS_Shape &theShape,
273 Standard_Real theTab[],
278 Standard_Real aShapeSize;
280 if (theShape.ShapeType() == TopAbs_VERTEX) {
281 aCenterMass = BRep_Tool::Pnt(TopoDS::Vertex(theShape));
282 } else if (theShape.ShapeType() == TopAbs_EDGE) {
283 BRepGProp::LinearProperties(theShape, aProps);
284 } else if (theShape.ShapeType() == TopAbs_FACE) {
285 BRepGProp::SurfaceProperties(theShape, aProps);
287 BRepGProp::VolumeProperties(theShape, aProps);
290 if (theShape.ShapeType() == TopAbs_VERTEX) {
293 aCenterMass = aProps.CentreOfMass();
294 aShapeSize = aProps.Mass();
297 theVertex = aCenterMass;
298 theTab[0] = theVertex.X();
299 theTab[1] = theVertex.Y();
300 theTab[2] = theVertex.Z();
301 theTab[3] = aShapeSize;
304 //=======================================================================
305 //function : GetInPlaceByHistory
307 //=======================================================================
308 Standard_Boolean GEOMAlgo_GetInPlaceAPI::GetInPlaceByHistory
309 (const Handle(GEOM_Function) &theWhereFunction,
310 const TopTools_IndexedMapOfShape &theWhereIndices,
311 const TopoDS_Shape &theWhat,
312 TopTools_ListOfShape &theShapesInPlace)
314 if (theWhereFunction.IsNull() || theWhat.IsNull())
315 return Standard_False;
317 if (theWhereIndices.Contains(theWhat)) {
318 // entity was not changed by the operation
319 theShapesInPlace.Append(theWhat);
321 return Standard_True;
324 // try to find in history
325 //TDF_Label aHistoryLabel = theWhereFunction->GetHistoryEntry(Standard_False);
327 // search in history for all argument shapes
328 Standard_Boolean isFound = Standard_False;
329 Standard_Boolean isGood = Standard_False;
331 TDF_LabelSequence aLabelSeq;
332 theWhereFunction->GetDependency(aLabelSeq);
333 Standard_Integer nbArg = aLabelSeq.Length();
335 for (Standard_Integer iarg = 1; iarg <= nbArg && !isFound; iarg++) {
337 TDF_Label anArgumentRefLabel = aLabelSeq.Value(iarg);
339 Handle(GEOM_Object) anArgumentObject = GEOM_Object::GetReferencedObject(anArgumentRefLabel);
340 TopoDS_Shape anArgumentShape = anArgumentObject->GetValue();
342 TopTools_IndexedMapOfShape anArgumentIndices;
343 TopExp::MapShapes(anArgumentShape, anArgumentIndices);
345 if (anArgumentIndices.Contains(theWhat)) {
346 isFound = Standard_True;
347 Standard_Integer aWhatIndex = anArgumentIndices.FindIndex(theWhat);
349 // Find corresponding label in history
350 TDF_Label anArgumentHistoryLabel =
351 theWhereFunction->GetArgumentHistoryEntry(anArgumentRefLabel, Standard_False);
352 if (anArgumentHistoryLabel.IsNull()) {
353 // Lost History of operation argument. Possibly, all its entities was removed.
354 isGood = Standard_True;
357 TDF_Label aWhatHistoryLabel = anArgumentHistoryLabel.FindChild(aWhatIndex, Standard_False);
359 if (aWhatHistoryLabel.IsNull()) {
360 // Removed entity ? Compound ? Compsolid ? Shell ? Wire
361 isGood = Standard_False;
363 Handle(TDataStd_IntegerArray) anIntegerArray;
364 if (!aWhatHistoryLabel.FindAttribute(TDataStd_IntegerArray::GetID(), anIntegerArray)) {
365 //Error: Empty modifications history for the sought shape.
366 isGood = Standard_False;
369 isGood = Standard_True;
370 Standard_Integer imod, aModifLen = anIntegerArray->Array()->Length();
371 for (imod = 1; imod <= aModifLen; imod++) {
372 const Standard_Integer anIndex =
373 anIntegerArray->Array()->Value(imod);
375 theShapesInPlace.Append(theWhereIndices.FindKey(anIndex));
386 // try compound/compsolid/shell/wire element by element
387 Standard_Boolean isFoundAny = Standard_False;
388 TopTools_MapOfShape mapShape;
390 if (theWhat.ShapeType() == TopAbs_COMPOUND ||
391 theWhat.ShapeType() == TopAbs_COMPSOLID) {
392 // recursive processing of compound/compsolid
393 TopoDS_Iterator anIt (theWhat, Standard_True, Standard_True);
394 for (; anIt.More(); anIt.Next()) {
395 if (mapShape.Add(anIt.Value())) {
396 TopoDS_Shape curWhat = anIt.Value();
397 isFoundAny = GetInPlaceByHistory(theWhereFunction, theWhereIndices, curWhat, theShapesInPlace);
398 if (isFoundAny) isFound = Standard_True;
402 else if (theWhat.ShapeType() == TopAbs_SHELL) {
403 // try to replace a shell by its faces images
404 TopExp_Explorer anExp (theWhat, TopAbs_FACE);
405 for (; anExp.More(); anExp.Next()) {
406 if (mapShape.Add(anExp.Current())) {
407 TopoDS_Shape curWhat = anExp.Current();
408 isFoundAny = GetInPlaceByHistory(theWhereFunction, theWhereIndices, curWhat, theShapesInPlace);
409 if (isFoundAny) isFound = Standard_True;
413 else if (theWhat.ShapeType() == TopAbs_WIRE) {
414 // try to replace a wire by its edges images
415 TopExp_Explorer anExp (theWhat, TopAbs_EDGE);
416 for (; anExp.More(); anExp.Next()) {
417 if (mapShape.Add(anExp.Current())) {
418 TopoDS_Shape curWhat = anExp.Current();
419 isFoundAny = GetInPlaceByHistory(theWhereFunction, theWhereIndices, curWhat, theShapesInPlace);
420 if (isFoundAny) isFound = Standard_True;
432 //=======================================================================
433 //function : GetInPlaceByHistory
435 //=======================================================================
437 GEOMAlgo_GetInPlaceAPI::GetInPlaceMap (const Handle(GEOM_Function) & theWhereFunction,
438 const TopoDS_Shape & theWhat,
439 std::vector< std::vector< int > > & theResVec)
443 if (theWhereFunction.IsNull() || theWhat.IsNull() || theWhereFunction->GetValue().IsNull() )
444 return Standard_False;
445 TopoDS_Shape theWhere = theWhereFunction->GetValue();
447 TopTools_IndexedMapOfShape whereIndices, whatIndices;
448 TopExp::MapShapes( theWhere, whereIndices );
449 TopExp::MapShapes( theWhat, whatIndices );
451 theResVec.resize( whatIndices.Extent() + 1 );
453 // first, try by history
455 Standard_Boolean isFound = Standard_False;
457 TDF_LabelSequence aLabelSeq;
458 theWhereFunction->GetDependency(aLabelSeq);
459 Standard_Integer nbArg = aLabelSeq.Length();
461 for (Standard_Integer iarg = 1; iarg <= nbArg && !isFound; iarg++)
463 TDF_Label anArgumentRefLabel = aLabelSeq.Value(iarg);
465 Handle(GEOM_Object) anArgumentObject = GEOM_Object::GetReferencedObject(anArgumentRefLabel);
466 TopoDS_Shape anArgumentShape = anArgumentObject->GetValue();
468 TopTools_IndexedMapOfShape anArgumentIndices;
469 TopExp::MapShapes(anArgumentShape, anArgumentIndices);
471 if (( isFound = anArgumentIndices.Contains(theWhat)))
473 // Find corresponding label in history
474 TDF_Label anArgumentHistoryLabel =
475 theWhereFunction->GetArgumentHistoryEntry(anArgumentRefLabel, Standard_False);
476 if ( anArgumentHistoryLabel.IsNull())
478 // Lost History of operation argument. Possibly, theWhat was removed from theWhere
484 Standard_Integer aWhatIndex = anArgumentIndices.FindIndex(theWhat);
485 for ( int i = 0, iSubWhat = aWhatIndex; i < whatIndices.Extent(); ++i, ++iSubWhat )
487 TDF_Label aHistoryLabel = anArgumentHistoryLabel.FindChild( iSubWhat, Standard_False );
488 if ( !aHistoryLabel.IsNull() )
490 Handle(TDataStd_IntegerArray) anIntegerArray;
491 if (aHistoryLabel.FindAttribute(TDataStd_IntegerArray::GetID(), anIntegerArray))
493 Standard_Integer imod, aModifLen = anIntegerArray->Array()->Length();
494 for ( imod = 1; imod <= aModifLen; imod++ )
496 Standard_Integer whereIndex = anIntegerArray->Array()->Value( imod );
497 const TopoDS_Shape& argSubShape = anArgumentIndices( iSubWhat );
498 Standard_Integer whatIndex = whatIndices.FindIndex( argSubShape );
499 theResVec[ whatIndex ].push_back( whereIndex );
508 if ( !isFound ) // use GetInPlace()
510 GEOMAlgo_GetInPlace gip;
511 if ( ! GetInPlace( theWhere, theWhat, gip ))
514 const TopTools_DataMapOfShapeListOfShape& img = gip.Images();
515 TopTools_DataMapIteratorOfDataMapOfShapeListOfShape imgIt( img );
516 for ( ; imgIt.More(); imgIt.Next() )
518 const TopoDS_Shape& whatSub = imgIt.Key();
519 const TopTools_ListOfShape& whereSubList = imgIt.Value();
520 int whatID = whatIndices.FindIndex( whatSub );
521 if ( whatID == 0 ) continue;
522 TopTools_ListIteratorOfListOfShape whereIt( whereSubList );
523 for ( ; whereIt.More(); whereIt.Next() )
525 int whereID = whereIndices.FindIndex( whereIt.Value() );
526 if ( whereID && whatSub.ShapeType() == whereIt.Value().ShapeType() )
527 theResVec[ whatID ].push_back( whereID );
535 // check that all sub-shapes are found and restore missing history of wires, shells etc.
536 for ( int iSubWhat = 1; iSubWhat <= whatIndices.Extent(); ++iSubWhat )
538 if ( !theResVec[ iSubWhat ].empty() )
540 const TopoDS_Shape& whatSubShape = whatIndices( iSubWhat );
541 switch ( whatSubShape.ShapeType() )
543 case TopAbs_COMPOUND:
544 case TopAbs_COMPSOLID:
545 continue; // not possible?
549 // find a corresponding sub-shape in theWhere
550 TColStd_MapOfInteger whereIDs;
551 TopAbs_ShapeEnum subType =
552 whatSubShape.ShapeType() == TopAbs_WIRE ? TopAbs_EDGE : TopAbs_FACE;
553 for ( TopExp_Explorer subIt( whatSubShape, subType ); subIt.More(); subIt.Next() )
555 int whatID = whatIndices.FindIndex( subIt.Current() );
556 std::vector< int > & whereIDsVec = theResVec[ whatID ];
557 for ( size_t i = 0; i < whereIDsVec.size(); ++i )
558 whereIDs.Add( whereIDsVec[i] );
560 // look for a Where sub-shape including all whereIDs
561 TopExp_Explorer whereIt( theWhere, whatSubShape.ShapeType() );
562 for ( ; whereIt.More(); whereIt.Next() )
565 for ( TopoDS_Iterator it( whereIt.Current() ); it.More() && isAllIn; it.Next() )
567 int whereID = whereIndices.FindIndex( it.Value() );
568 isAllIn = whereIDs.Contains( whereID );
572 theResVec[ iSubWhat ].push_back( whereIndices.FindIndex( whereIt.Current() ));
577 default:; // removed sub-shape