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