1 // Copyright (C) 2007-2011 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.
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
23 #include <Standard_Stream.hxx>
25 #include <GEOMImpl_HealingDriver.hxx>
26 #include <GEOMImpl_Types.hxx>
27 #include <GEOMImpl_IHealing.hxx>
28 #include <GEOM_Function.hxx>
30 #include <GEOMImpl_GlueDriver.hxx>
32 #include <ShHealOper_ShapeProcess.hxx>
33 #include <ShHealOper_RemoveFace.hxx>
34 #include <ShHealOper_CloseContour.hxx>
35 #include <ShHealOper_RemoveInternalWires.hxx>
36 #include <ShHealOper_FillHoles.hxx>
37 #include <ShHealOper_Sewing.hxx>
38 #include <ShHealOper_EdgeDivide.hxx>
39 #include <ShHealOper_ChangeOrientation.hxx>
41 #include <BRep_Builder.hxx>
45 #include <TopoDS_Iterator.hxx>
46 #include <TopTools_IndexedMapOfShape.hxx>
48 #include <TColStd_IndexedDataMapOfTransientTransient.hxx>
49 #include <TNaming_CopyShape.hxx>
50 #include <ShapeFix_ShapeTolerance.hxx>
51 #include <ShapeFix_Shape.hxx>
52 #include <BRepCheck_Analyzer.hxx>
54 #include <Precision.hxx>
56 #include <StdFail_NotDone.hxx>
58 //=======================================================================
59 //function : raiseNotDoneExeption
60 //purpose : global function: forms error message and raises exeption
61 //=======================================================================
62 void raiseNotDoneExeption( const int theErrorStatus )
64 switch ( theErrorStatus )
66 case ShHealOper_NotError: StdFail_NotDone::Raise( "ShHealOper_NotError_msg" );
67 case ShHealOper_InvalidParameters: StdFail_NotDone::Raise( "ShHealOper_InvalidParameters_msg" );
68 case ShHealOper_ErrorExecution:
69 default: StdFail_NotDone::Raise( "ShHealOper_ErrorExecution_msg" );
73 //=======================================================================
76 //=======================================================================
77 const Standard_GUID& GEOMImpl_HealingDriver::GetID()
79 static Standard_GUID aHealingDriver("FF1BBB61-5D14-4df2-980B-3A668264EA16");
80 return aHealingDriver;
83 //=======================================================================
84 //function : GEOMImpl_HealingDriver
86 //=======================================================================
87 GEOMImpl_HealingDriver::GEOMImpl_HealingDriver()
91 //=======================================================================
94 //=======================================================================
95 Standard_Integer GEOMImpl_HealingDriver::Execute(TFunction_Logbook& log) const
97 if (Label().IsNull()) return 0;
98 Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction(Label());
100 if (aFunction.IsNull()) return 0;
102 GEOMImpl_IHealing HI (aFunction);
103 Standard_Integer aType = aFunction->GetType();
104 Handle(GEOM_Function) anOriginalFunction = HI.GetOriginal();
105 if (anOriginalFunction.IsNull()) return 0;
106 TopoDS_Shape aShape, anOriginalShape = anOriginalFunction->GetValue();
107 if (anOriginalShape.IsNull()) return 0;
112 ShapeProcess(&HI, anOriginalShape, aShape);
115 SuppressFaces(&HI, anOriginalShape, aShape);
118 CloseContour(&HI, anOriginalShape, aShape);
120 case REMOVE_INT_WIRES:
121 RemoveIntWires(&HI, anOriginalShape, aShape);
124 RemoveHoles(&HI, anOriginalShape, aShape);
127 Sew(&HI, anOriginalShape, aShape);
130 AddPointOnEdge(&HI, anOriginalShape, aShape);
132 case CHANGE_ORIENTATION:
133 ChangeOrientation(&HI, anOriginalShape, aShape);
135 case LIMIT_TOLERANCE:
136 LimitTolerance(&HI, anOriginalShape, aShape);
143 raiseNotDoneExeption( ShHealOper_ErrorExecution );
145 aFunction->SetValue(aShape);
147 log.SetTouched(Label());
151 //=======================================================================
152 //function : ShapeProcess
154 //=======================================================================
155 Standard_Boolean GEOMImpl_HealingDriver::ShapeProcess (GEOMImpl_IHealing* theHI,
156 const TopoDS_Shape& theOriginalShape,
157 TopoDS_Shape& theOutShape) const
159 Handle(TColStd_HArray1OfExtendedString) anOperators = theHI->GetOperators();
160 Handle(TColStd_HArray1OfExtendedString) aParams = theHI->GetParameters();
161 Handle(TColStd_HArray1OfExtendedString) aValues = theHI->GetValues();
163 if (anOperators.IsNull() || anOperators->Length() <= 0)
164 return Standard_False;
166 Standard_Integer nbParams = 0, nbValues = 0;
167 if (!aParams.IsNull()) {
168 nbParams = aParams->Length();
170 if (!aValues.IsNull()) {
171 nbValues = aValues->Length();
173 if (nbParams != nbValues)
174 return Standard_False;
176 ShHealOper_ShapeProcess aHealer;
177 TColStd_SequenceOfAsciiString anOperatorsAS, aParamsAS, aValuesAS;
179 for (i = 1; i <= anOperators->Length(); i++)
180 anOperatorsAS.Append(TCollection_AsciiString(anOperators->Value(i)));
182 aHealer.SetOperators(anOperatorsAS);
184 for (i = 1; i <= nbParams; i++) {
185 aHealer.SetParameter(TCollection_AsciiString(aParams->Value(i)),
186 TCollection_AsciiString(aValues->Value(i)));
189 aHealer.Perform(theOriginalShape, theOutShape);
191 if (!aHealer.isDone())
192 raiseNotDoneExeption( ShHealOper_NotError );
194 return Standard_True;
197 //=======================================================================
198 //function : SupressFaces
200 //=======================================================================
201 void SuppressFacesRec (const TopTools_SequenceOfShape& theShapesFaces,
202 const TopoDS_Shape& theOriginalShape,
203 TopoDS_Shape& theOutShape)
205 if ((theOriginalShape.ShapeType() != TopAbs_COMPOUND &&
206 theOriginalShape.ShapeType() != TopAbs_COMPSOLID))
208 ShHealOper_RemoveFace aHealer (theOriginalShape);
209 Standard_Boolean aResult = aHealer.Perform(theShapesFaces);
212 theOutShape = aHealer.GetResultShape();
214 raiseNotDoneExeption(aHealer.GetErrorStatus());
222 TopTools_MapOfShape mapShape;
223 TopoDS_Iterator It (theOriginalShape, Standard_True, Standard_True);
225 for (; It.More(); It.Next()) {
226 TopoDS_Shape aShape_i = It.Value();
227 if (mapShape.Add(aShape_i)) {
228 // check, if current shape contains at least one of faces to be removed
229 bool isFound = false;
230 TopTools_IndexedMapOfShape aShapes_i;
231 TopExp::MapShapes(aShape_i, aShapes_i);
232 for (int i = 1; i <= theShapesFaces.Length() && !isFound; i++) {
233 const TopoDS_Shape& aFace_i = theShapesFaces.Value(i);
234 if (aShapes_i.Contains(aFace_i)) isFound = true;
237 TopoDS_Shape anOutSh_i;
238 SuppressFacesRec(theShapesFaces, aShape_i, anOutSh_i);
239 if ( !anOutSh_i.IsNull() )
240 BB.Add(CC, anOutSh_i);
244 BB.Add(CC, aShape_i);
252 Standard_Boolean GEOMImpl_HealingDriver::SuppressFaces (GEOMImpl_IHealing* theHI,
253 const TopoDS_Shape& theOriginalShape,
254 TopoDS_Shape& theOutShape) const
256 Handle(TColStd_HArray1OfInteger) aFaces = theHI->GetFaces();
258 Standard_Boolean aResult = Standard_False;
260 if (aFaces.IsNull()) {
261 ShHealOper_RemoveFace aHealer (theOriginalShape);
262 aResult = aHealer.Perform();
265 theOutShape = aHealer.GetResultShape();
267 raiseNotDoneExeption(aHealer.GetErrorStatus());
270 TopTools_SequenceOfShape aShapesFaces;
271 TopTools_IndexedMapOfShape aShapes;
272 TopExp::MapShapes(theOriginalShape, aShapes);
273 for (int i = 1; i <= aFaces->Length(); i++) {
274 int indexOfFace = aFaces->Value(i);
275 TopoDS_Shape aFace = aShapes.FindKey(indexOfFace);
276 aShapesFaces.Append(aFace);
278 SuppressFacesRec(aShapesFaces, theOriginalShape, theOutShape);
279 if ((theOriginalShape.ShapeType() == TopAbs_COMPOUND ||
280 theOriginalShape.ShapeType() == TopAbs_COMPSOLID)) {
281 TopoDS_Shape aSh = theOutShape;
282 theOutShape = GEOMImpl_GlueDriver::GlueFaces(aSh, Precision::Confusion(), Standard_True);
286 return Standard_True;
289 //=======================================================================
290 //function : CloseContour
292 //=======================================================================
293 Standard_Boolean GEOMImpl_HealingDriver::CloseContour (GEOMImpl_IHealing* theHI,
294 const TopoDS_Shape& theOriginalShape,
295 TopoDS_Shape& theOutShape) const
297 Standard_Boolean isByVertex = theHI->GetIsCommonVertex();
298 Handle(TColStd_HArray1OfInteger) aWires = theHI->GetWires();
300 ShHealOper_CloseContour aHealer (theOriginalShape);
302 Standard_Boolean aResult = Standard_False;
303 if ( aWires.IsNull() ) {
304 if ( theOriginalShape.ShapeType() == TopAbs_WIRE )
305 aResult = aHealer.Perform(TopoDS::Wire(theOriginalShape), isByVertex, !isByVertex);
308 TopTools_SequenceOfShape aShapesWires;
309 TopTools_IndexedMapOfShape aShapes;
310 TopExp::MapShapes(theOriginalShape, aShapes);
311 for (int i = 1; i <= aWires->Length(); i++) {
312 int indexOfWire = aWires->Value(i);
313 TopoDS_Shape aWire = aShapes.FindKey(indexOfWire);
314 aShapesWires.Append(aWire);
317 aResult = aHealer.Perform( aShapesWires, isByVertex, !isByVertex );
321 theOutShape = aHealer.GetResultShape();
323 raiseNotDoneExeption( aHealer.GetErrorStatus() );
328 //=======================================================================
329 //function : RemoveIntWires
331 //=======================================================================
332 Standard_Boolean GEOMImpl_HealingDriver::RemoveIntWires (GEOMImpl_IHealing* theHI,
333 const TopoDS_Shape& theOriginalShape,
334 TopoDS_Shape& theOutShape) const
336 Handle(TColStd_HArray1OfInteger) aWires = theHI->GetWires();
338 ShHealOper_RemoveInternalWires aHealer(theOriginalShape);
340 Standard_Boolean aResult = Standard_False;
341 if (aWires.IsNull()) { // remove all faces
342 aResult = aHealer.Remove();
344 TopTools_SequenceOfShape aShapesWires;
345 TopTools_IndexedMapOfShape aShapes;
346 TopExp::MapShapes(theOriginalShape, aShapes);
347 for (int i = 1; i <= aWires->Length(); i++) {
348 int indexOfWire = aWires->Value(i);
349 TopoDS_Shape aWire = aShapes.FindKey(indexOfWire);
350 aShapesWires.Append(aWire);
353 aResult = aHealer.Remove(aShapesWires);
357 theOutShape = aHealer.GetResultShape();
359 raiseNotDoneExeption( aHealer.GetErrorStatus() );
364 //=======================================================================
365 //function : RemoveHoles
367 //=======================================================================
368 Standard_Boolean GEOMImpl_HealingDriver::RemoveHoles (GEOMImpl_IHealing* theHI,
369 const TopoDS_Shape& theOriginalShape,
370 TopoDS_Shape& theOutShape) const
372 Handle(TColStd_HArray1OfInteger) aWires = theHI->GetWires();
374 ShHealOper_FillHoles aHealer (theOriginalShape);
376 Standard_Boolean aResult = Standard_False;
377 if (aWires.IsNull()) { // remove all faces
378 aResult = aHealer.Fill();
380 TopTools_SequenceOfShape aShapesWires;
381 TopTools_IndexedMapOfShape aShapes;
382 TopExp::MapShapes(theOriginalShape, aShapes);
383 for (int i = 1; i <= aWires->Length(); i++) {
384 int indexOfWire = aWires->Value(i);
385 TopoDS_Shape aWire = aShapes.FindKey(indexOfWire);
386 aShapesWires.Append(aWire);
389 aResult = aHealer.Fill(aShapesWires);
393 theOutShape = aHealer.GetResultShape();
395 raiseNotDoneExeption( aHealer.GetErrorStatus() );
400 //=======================================================================
403 //=======================================================================
404 Standard_Boolean GEOMImpl_HealingDriver::Sew (GEOMImpl_IHealing* theHI,
405 const TopoDS_Shape& theOriginalShape,
406 TopoDS_Shape& theOutShape) const
408 Standard_Real aTol = theHI->GetTolerance();
410 ShHealOper_Sewing aHealer (theOriginalShape, aTol);
412 Standard_Boolean aResult = aHealer.Perform();
415 theOutShape = aHealer.GetResultShape();
417 raiseNotDoneExeption( aHealer.GetErrorStatus() );
422 //=======================================================================
423 //function : AddPointOnEdge
425 //=======================================================================
426 Standard_Boolean GEOMImpl_HealingDriver::AddPointOnEdge (GEOMImpl_IHealing* theHI,
427 const TopoDS_Shape& theOriginalShape,
428 TopoDS_Shape& theOutShape) const
430 Standard_Boolean isByParameter = theHI->GetIsByParameter();
431 Standard_Integer anIndex = theHI->GetIndex();
432 Standard_Real aValue = theHI->GetDevideEdgeValue();
434 ShHealOper_EdgeDivide aHealer (theOriginalShape);
436 Standard_Boolean aResult = Standard_False;
437 if (anIndex == -1) { // apply algorythm for the whole shape which is EDGE
438 if (theOriginalShape.ShapeType() == TopAbs_EDGE)
439 aResult = aHealer.Perform(TopoDS::Edge(theOriginalShape), aValue, isByParameter);
441 TopTools_IndexedMapOfShape aShapes;
442 TopExp::MapShapes(theOriginalShape, aShapes);
443 TopoDS_Shape aEdgeShape = aShapes.FindKey(anIndex);
444 if (aEdgeShape.ShapeType() == TopAbs_EDGE)
445 aResult = aHealer.Perform(TopoDS::Edge(aEdgeShape), aValue, isByParameter);
449 theOutShape = aHealer.GetResultShape();
451 raiseNotDoneExeption( aHealer.GetErrorStatus() );
457 //=======================================================================
458 //function : ChangeOrientation
460 //=======================================================================
461 Standard_Boolean GEOMImpl_HealingDriver::ChangeOrientation (GEOMImpl_IHealing* theHI,
462 const TopoDS_Shape& theOriginalShape,
463 TopoDS_Shape& theOutShape) const
465 ShHealOper_ChangeOrientation aHealer (theOriginalShape);
467 Standard_Boolean aResult = aHealer.Perform();
470 theOutShape = aHealer.GetResultShape();
472 raiseNotDoneExeption( aHealer.GetErrorStatus() );
477 //=======================================================================
478 //function : LimitTolerance
480 //=======================================================================
481 void GEOMImpl_HealingDriver::LimitTolerance (GEOMImpl_IHealing* theHI,
482 const TopoDS_Shape& theOriginalShape,
483 TopoDS_Shape& theOutShape) const
485 Standard_Real aTol = theHI->GetTolerance();
486 if (aTol < Precision::Confusion())
487 aTol = Precision::Confusion();
489 // 1. Make a copy to prevent the original shape changes.
490 TopoDS_Shape aShapeCopy;
491 TColStd_IndexedDataMapOfTransientTransient aMapTShapes;
492 TNaming_CopyShape::CopyTool(theOriginalShape, aMapTShapes, aShapeCopy);
494 // 2. Limit tolerance.
495 ShapeFix_ShapeTolerance aSFT;
496 aSFT.LimitTolerance(aShapeCopy, aTol, aTol, TopAbs_SHAPE);
498 // 3. Fix obtained shape.
499 Handle(ShapeFix_Shape) aSfs = new ShapeFix_Shape (aShapeCopy);
501 theOutShape = aSfs->Shape();
503 BRepCheck_Analyzer ana (theOutShape, Standard_True);
505 StdFail_NotDone::Raise("Non valid shape result");
508 //=======================================================================
509 //function : GEOMImpl_HealingDriver_Type_
511 //=======================================================================
512 Standard_EXPORT Handle_Standard_Type& GEOMImpl_HealingDriver_Type_()
515 static Handle_Standard_Type aType1 = STANDARD_TYPE(TFunction_Driver);
516 if ( aType1.IsNull()) aType1 = STANDARD_TYPE(TFunction_Driver);
517 static Handle_Standard_Type aType2 = STANDARD_TYPE(MMgt_TShared);
518 if ( aType2.IsNull()) aType2 = STANDARD_TYPE(MMgt_TShared);
519 static Handle_Standard_Type aType3 = STANDARD_TYPE(Standard_Transient);
520 if ( aType3.IsNull()) aType3 = STANDARD_TYPE(Standard_Transient);
523 static Handle_Standard_Transient _Ancestors[]= {aType1,aType2,aType3,NULL};
524 static Handle_Standard_Type _aType = new Standard_Type("GEOMImpl_HealingDriver",
525 sizeof(GEOMImpl_HealingDriver),
527 (Standard_Address)_Ancestors,
528 (Standard_Address)NULL);
533 //=======================================================================
534 //function : DownCast
536 //=======================================================================
538 const Handle(GEOMImpl_HealingDriver) Handle(GEOMImpl_HealingDriver)::DownCast(const Handle(Standard_Transient)& AnObject)
540 Handle(GEOMImpl_HealingDriver) _anOtherObject;
542 if (!AnObject.IsNull()) {
543 if (AnObject->IsKind(STANDARD_TYPE(GEOMImpl_HealingDriver))) {
544 _anOtherObject = Handle(GEOMImpl_HealingDriver)((Handle(GEOMImpl_HealingDriver)&)AnObject);
548 return _anOtherObject;