Salome HOME
Update copyright information
[modules/geom.git] / src / ShHealOper / ShHealOper_EdgeDivide.cxx
1 //  Copyright (C) 2007-2008  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 //  Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
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.
10 //
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.
15 //
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
19 //
20 //  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22 // File:      ShHealOper_EdgeDivide.cxx
23 // Created:   30.04.04 16:44:47
24 // Author:    Galina KULIKOVA
25 //
26 #include <ShHealOper_EdgeDivide.hxx>
27 #include <ShapeUpgrade_WireDivide.hxx>
28 #include <ShHealOper_SplitCurve3d.hxx>
29 #include <ShHealOper_SplitCurve2d.hxx>
30 #include <TopTools_ListOfShape.hxx>
31 #include <TopTools_ListIteratorOfListOfShape.hxx>
32 #include <BRep_Tool.hxx>
33 #include <ShapeFix_Edge.hxx>
34 #include <ShapeAnalysis_Edge.hxx>
35 #include <GeomAdaptor_Curve.hxx>
36 #include <Geom2dAdaptor_Curve.hxx>
37 #include <TopoDS.hxx>
38 #include <Geom_Curve.hxx>
39 #include <TopoDS_Face.hxx>
40 #include <Geom2d_Curve.hxx>
41 #include <GCPnts_AbscissaPoint.hxx>
42 #include <TopExp.hxx>
43 #include <Precision.hxx>
44 //#include <.hxx>
45 //#include <.hxx>
46 //=======================================================================
47 //function : ShHealOper_EdgeDivide()
48 //purpose  : Constructor
49 //=======================================================================
50
51 ShHealOper_EdgeDivide::ShHealOper_EdgeDivide (const TopoDS_Shape& theShape) 
52 {
53   Init(theShape);
54 }
55 //=======================================================================
56 //function : Init
57 //purpose  : 
58 //=======================================================================
59
60 void ShHealOper_EdgeDivide::Init(const TopoDS_Shape& theShape)
61 {
62   ShHealOper_Tool::Init(theShape);
63   myDivideParamMode = Standard_True;
64   myMapEdgesFace.Clear();
65   TopExp::MapShapesAndAncestors(theShape,TopAbs_EDGE,TopAbs_FACE,myMapEdgesFace);
66   
67 }
68
69 //=======================================================================
70 //function : Perform
71 //purpose  : 
72 //=======================================================================
73 Standard_Boolean ShHealOper_EdgeDivide::Perform(const TopoDS_Shape& theEdge, 
74                                                 const TColStd_SequenceOfReal& theValues,
75                                                 const Standard_Boolean theDivideParamMode)
76
77   myDone = Standard_False;
78   myDivideParamMode = theDivideParamMode;
79   if(theEdge.ShapeType() != TopAbs_EDGE) {
80     myErrorStatus = ShHealOper_InvalidParameters;
81     return myDone;
82   }
83   myEdge = TopoDS::Edge(theEdge);
84   Standard_Integer i =1;
85   Handle(TColStd_HSequenceOfReal) aSeqValues = new TColStd_HSequenceOfReal;
86   for( ; i <= theValues.Length(); i++)
87       aSeqValues->Append(theValues.Value(i));
88   myDone = build(aSeqValues);
89   return myDone;
90   
91 }
92 //=======================================================================
93 //function : Perform
94 //purpose  : 
95 //=======================================================================
96
97 Standard_Boolean ShHealOper_EdgeDivide::Perform(const TopoDS_Shape& theEdge, 
98                                                 const Standard_Real theValue,
99                                                 const Standard_Boolean theDivideParamMode)
100 {
101   myDone = Standard_False;
102   myErrorStatus = ShHealOper_NotError;
103   if(theEdge.ShapeType() != TopAbs_EDGE) {
104     myErrorStatus = ShHealOper_InvalidParameters;
105     return myDone;
106   }
107   myDivideParamMode = theDivideParamMode;
108   myEdge = TopoDS::Edge(theEdge);
109   Handle(TColStd_HSequenceOfReal) aSeqValues = new TColStd_HSequenceOfReal;
110   aSeqValues->Append(theValue);
111   myDone = build(aSeqValues);
112   return myDone;
113 }
114 //=======================================================================
115 //function : build
116 //purpose  : 
117 //=======================================================================
118
119 Standard_Boolean ShHealOper_EdgeDivide::build(const Handle(TColStd_HSequenceOfReal)& theValues)
120 {
121   if(myEdge.IsNull() || !theValues->Length()) {
122     myErrorStatus = ShHealOper_InvalidParameters;
123     return Standard_False;
124   }
125
126   Standard_Boolean has3d = Standard_False, 
127   has2d = Standard_False, 
128   hasPCurves = Standard_False;
129   
130   //computation of the split values in dependance from specified mode and values.
131   if(!computeValues(theValues, has3d,has2d,hasPCurves)) {
132     myErrorStatus = ShHealOper_InvalidParameters;
133     return Standard_False;
134   }
135   
136   //setting split values in the splitting curve tools.
137   Handle(ShapeUpgrade_WireDivide) aSplitTool = new ShapeUpgrade_WireDivide;
138   aSplitTool->Load(myEdge);
139   aSplitTool->SetContext(myContext);
140   if(has3d) {
141     Handle(ShHealOper_SplitCurve3d) aSplitCurve3d = new ShHealOper_SplitCurve3d;
142     aSplitCurve3d->SetValues(theValues);
143     aSplitTool->SetSplitCurve3dTool(aSplitCurve3d);
144   }
145   else if(has2d) {
146     Handle(ShHealOper_SplitCurve2d) aSplitCurve2d = new ShHealOper_SplitCurve2d;
147     aSplitCurve2d->SetValues(theValues);
148     aSplitTool->SetSplitCurve2dTool(aSplitCurve2d);
149   }
150   else {
151     myErrorStatus = ShHealOper_InvalidParameters;
152     return Standard_False;
153   }
154   
155   //split 3d curve and pcurve for each face reffering to edge.
156   Standard_Boolean isDone = Standard_True;
157   if(hasPCurves) {
158     const TopTools_ListOfShape& lfaces  = myMapEdgesFace.FindFromKey(myEdge);
159     TopTools_ListIteratorOfListOfShape aItf(lfaces);
160     for( ; aItf.More() && isDone; aItf.Next()) {
161       TopoDS_Face aFace = TopoDS::Face(aItf.Value());
162       aSplitTool->SetFace(aFace);
163       aSplitTool->Perform();
164       isDone = aSplitTool->Status( ShapeExtend_DONE );
165       if( aSplitTool->Status( ShapeExtend_FAIL ))
166         myErrorStatus = ShHealOper_ErrorExecution;
167     }
168   }
169   else {
170      aSplitTool->Perform();
171      isDone = aSplitTool->Status( ShapeExtend_DONE );
172      if( aSplitTool->Status( ShapeExtend_FAIL ))
173         myErrorStatus = ShHealOper_ErrorExecution;
174   }
175   if(isDone)
176     myResultShape = myContext->Apply(myInitShape);
177   return isDone;
178   
179 }
180 //=======================================================================
181 //function : computeValues
182 //purpose  : 
183 //=======================================================================
184
185 Standard_Boolean ShHealOper_EdgeDivide::computeValues(const Handle(TColStd_HSequenceOfReal)& theValues,
186                                                       Standard_Boolean& theHas3d,
187                                                       Standard_Boolean& theHas2d,
188                                                       Standard_Boolean& hasPCurves)
189 {
190   hasPCurves = (myMapEdgesFace.Contains(myEdge) && 
191                 myMapEdgesFace.FindFromKey(myEdge).Extent());
192   if(hasPCurves && (!BRep_Tool::SameRange(myEdge) || !BRep_Tool::SameParameter(myEdge))) {
193     ShapeFix_Edge sfe;
194     sfe.FixSameParameter(myEdge);
195   }
196   
197   Standard_Real aFirst =0.,aLast=0.;
198
199   //computation of the split values if edge should be splitted by parameter.
200   if(myDivideParamMode) {
201     BRep_Tool::Range(myEdge,aFirst,aLast);
202     Handle(Geom_Curve) aCurve = BRep_Tool::Curve(myEdge,aFirst,aLast);
203     
204     theHas3d = (!aCurve.IsNull());
205     theHas2d = (aCurve.IsNull() && (fabs(aLast-aFirst) > Precision::PConfusion() ));
206     Standard_Integer i = 1;
207     for( ; i <= theValues->Length();i++) {
208       Standard_Real aVal = theValues->Value(i);
209       theValues->ChangeValue(i) = aFirst+ aVal*fabs(aLast - aFirst);
210     }
211   }
212   else {
213      //computation of the split values if edge should be splitted by length.
214     ShapeAnalysis_Edge sae;
215     Handle(Geom_Curve) aCurve;
216     Standard_Real aCurLen =0.;
217     GeomAdaptor_Curve aAdC;
218     Geom2dAdaptor_Curve aAdC2d;
219     if(sae.Curve3d(myEdge,aCurve,aFirst,aLast,Standard_False)) {
220       aAdC.Load(aCurve,aFirst,aLast);
221       aCurLen = GCPnts_AbscissaPoint::Length(aAdC,aFirst,aLast); 
222       theHas3d = Standard_True;
223     }
224     else {
225       if(hasPCurves) {
226         TopoDS_Face aFace = TopoDS::Face(myMapEdgesFace.FindFromKey(myEdge).First());
227         Handle(Geom2d_Curve) aCurve2d;
228         if(sae.PCurve(myEdge,aFace,aCurve2d,aFirst,aLast)) {
229           aAdC2d.Load(aCurve2d,aFirst,aLast);
230           aCurLen = GCPnts_AbscissaPoint::Length(aAdC,aFirst,aLast);
231           theHas2d = Standard_True;
232         }
233           
234       }
235     }
236     if(!theHas3d && !theHas2d)
237       return Standard_False;
238
239     Standard_Integer i = 1;
240     for( ; i <= theValues->Length();i++) {
241       Standard_Real aLen = theValues->Value(i)*aCurLen;
242       if(theHas3d) {
243         GCPnts_AbscissaPoint anAbsc(aAdC,aLen,aFirst);
244         if(anAbsc.IsDone()) 
245           theValues->ChangeValue(i) = anAbsc.Parameter();
246         else
247           theValues->Remove(i--);
248       }
249       else if(theHas2d) {
250         GCPnts_AbscissaPoint anAbsc(aAdC2d,aLen,aFirst);
251         if(anAbsc.IsDone()) 
252           theValues->ChangeValue(i) = anAbsc.Parameter();
253         else
254           theValues->Remove(i--);
255       }
256     }
257   }
258   return (theValues->Length());
259 }