0024135: Result of reading step file is invalid.
[occt.git] / src / StepToGeom / StepToGeom_MakeTrimmedCurve.cxx
1 // Created on: 1994-11-04
2 // Created by: Frederic MAUPAS
3 // Copyright (c) 1994-1999 Matra Datavision
4 // Copyright (c) 1999-2012 OPEN CASCADE SAS
5 //
6 // The content of this file is subject to the Open CASCADE Technology Public
7 // License Version 6.5 (the "License"). You may not use the content of this file
8 // except in compliance with the License. Please obtain a copy of the License
9 // at http://www.opencascade.org and read it completely before using this file.
10 //
11 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
12 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
13 //
14 // The Original Code and all software distributed under the License is
15 // distributed on an "AS IS" basis, without warranty of any kind, and the
16 // Initial Developer hereby disclaims all such warranties, including without
17 // limitation, any warranties of merchantability, fitness for a particular
18 // purpose or non-infringement. Please see the License for the specific terms
19 // and conditions governing the rights and limitations under the License.
20
21 //:n9 abv 16.02.99: PRO10107: check parameters on curve with PConfusion()!
22 //:o6 abv 18.02.99: r0301_db #63077: application of parameter Factor moved
23 //:p0 abv 19.02.99: management of 'done' flag improved
24 //:p3 abv 23.02.99: bm4_id_punch_d.stp #1313: shift of parameters on ellipse with R1 < R2
25 //    abv 09.02.99: S4136: eliminate using BRepAPI::Precision()
26
27 #include <StepToGeom_MakeTrimmedCurve.ixx>
28 #include <gp_Pnt.hxx>
29 #include <Geom_CartesianPoint.hxx>
30 #include <Geom_Curve.hxx>
31 #include <StepGeom_CartesianPoint.hxx>
32 #include <StepGeom_Line.hxx>
33 #include <StepGeom_Vector.hxx>
34 #include <StepGeom_Circle.hxx>
35 #include <StepGeom_Ellipse.hxx>
36 #include <StepGeom_Parabola.hxx>
37 #include <StepGeom_Hyperbola.hxx>
38 #include <StepGeom_TrimmingSelect.hxx>
39 #include <StepGeom_HArray1OfTrimmingSelect.hxx>
40 #include <StepGeom_TrimmedCurve.hxx>
41 #include <StepToGeom_MakeTrimmedCurve.hxx>
42 #include <StepToGeom_MakeCartesianPoint.hxx>
43 #include <StepToGeom_MakeCurve.hxx>
44 //#include <GeomAPI_ProjectPointOnCurve.hxx>
45 //#include <BRepAPI.hxx>
46 #include <ElCLib.hxx>
47
48 #include <UnitsMethods.hxx>
49 #include <Precision.hxx>
50 #include <ShapeAnalysis_Curve.hxx>
51 #include <StepGeom_Axis2Placement3d.hxx>
52
53 // ----------------------------------------------------------------
54 // ExtractParameter
55 // ----------------------------------------------------------------
56 //:o6 abv 18 Feb 99: parameter Factor added
57 //:p3 abv 23 Feb 99: parameter Shift added
58
59 static Standard_Boolean  ExtractParameter
60 (const Handle(Geom_Curve) &  aGeomCurve,
61  const Handle(StepGeom_HArray1OfTrimmingSelect) & TS,
62  const Standard_Integer nbSel,
63  const Standard_Integer MasterRep,
64  const Standard_Real Factor,
65  const Standard_Real Shift,
66  Standard_Real & aParam)     
67 {
68   Handle(StepGeom_CartesianPoint) aPoint;
69   Handle(Geom_CartesianPoint) theGeomPnt;
70   Standard_Integer i;
71 //:S4136  Standard_Real precBrep = BRepAPI::Precision();
72   for ( i = 1 ; i <= nbSel ; i++) {
73     StepGeom_TrimmingSelect theSel = TS->Value(i);
74     if (MasterRep == 2 && theSel.CaseMember() > 0) {
75       aParam = Shift + Factor * theSel.ParameterValue();
76       return Standard_True;
77     }
78     else if (MasterRep == 1 && theSel.CaseNumber() > 0) {
79       aPoint = theSel.CartesianPoint();
80           StepToGeom_MakeCartesianPoint::Convert(aPoint,theGeomPnt);
81       gp_Pnt thegpPnt = theGeomPnt->Pnt();
82       
83       //:S4136: use advanced algorithm
84       ShapeAnalysis_Curve sac;
85       gp_Pnt p;
86       sac.Project ( aGeomCurve, thegpPnt, Precision::Confusion(), p, aParam );
87 /* //:S4136
88       //Trim == natural boundary ?
89       if(aGeomCurve->IsKind(STANDARD_TYPE(Geom_BoundedCurve))) {
90         Standard_Real frstPar = aGeomCurve->FirstParameter();
91         Standard_Real lstPar = aGeomCurve->LastParameter();
92         gp_Pnt frstPnt = aGeomCurve->Value(frstPar);
93         gp_Pnt lstPnt = aGeomCurve->Value(lstPar);
94         if(frstPnt.IsEqual(thegpPnt,precBrep)) {
95           aParam = frstPar;
96           return Standard_True;
97         }
98         if(lstPnt.IsEqual(thegpPnt,precBrep)) {
99           aParam = lstPar;
100           return Standard_True;
101         }
102       }
103       // Project Point On Curve
104       GeomAPI_ProjectPointOnCurve PPOC(thegpPnt, aGeomCurve);
105       if (PPOC.NbPoints() == 0) {
106         return Standard_False;
107       }
108       aParam = PPOC.LowerDistanceParameter();
109 */
110       return Standard_True;
111     }
112   }
113 // if the MasterRepresentation is unspecified:
114 // if a ParameterValue exists, it is prefered
115
116   for ( i = 1 ; i <= nbSel ; i++) {
117     StepGeom_TrimmingSelect theSel = TS->Value(i);
118     if (theSel.CaseMember() > 0) {
119       aParam = Shift + Factor * theSel.ParameterValue();
120       
121       return Standard_True;
122     }
123   }
124 // if no ParameterValue exists, it is created from the CartesianPointValue
125
126   for ( i = 1 ; i <= nbSel ; i++) {
127     StepGeom_TrimmingSelect theSel = TS->Value(i);
128     if (theSel.CaseNumber() > 0) {
129       aPoint = theSel.CartesianPoint();
130           StepToGeom_MakeCartesianPoint::Convert(aPoint,theGeomPnt);
131       gp_Pnt thegpPnt = theGeomPnt->Pnt();
132       // Project Point On Curve
133       ShapeAnalysis_Curve sac;
134       gp_Pnt p;
135       sac.Project ( aGeomCurve, thegpPnt, Precision::Confusion(), p, aParam );
136 /*
137       GeomAPI_ProjectPointOnCurve PPOC(thegpPnt, aGeomCurve);
138       if (PPOC.NbPoints() == 0) {
139         return Standard_False;
140       }
141       aParam = PPOC.LowerDistanceParameter();
142 */
143       return Standard_True;
144     }
145   }
146   return Standard_False;  // I suppose
147 }
148
149
150 //=============================================================================
151 // Creation d' une Trimmed Curve de Geom a partir d' une Trimmed Curve de Step
152 //=============================================================================
153
154 Standard_Boolean StepToGeom_MakeTrimmedCurve::Convert (const Handle(StepGeom_TrimmedCurve)& SC, Handle(Geom_TrimmedCurve)& CC)
155 {
156   const Handle(StepGeom_Curve) theSTEPCurve = SC->BasisCurve();
157   Handle(Geom_Curve) theCurve;
158   if (!StepToGeom_MakeCurve::Convert(theSTEPCurve,theCurve))
159     return Standard_False;
160
161   const Handle(StepGeom_HArray1OfTrimmingSelect)& theTrimSel1 = SC->Trim1();
162   const Handle(StepGeom_HArray1OfTrimmingSelect)& theTrimSel2 = SC->Trim2();
163   const Standard_Integer nbSel1 = SC->NbTrim1();
164   const Standard_Integer nbSel2 = SC->NbTrim2();
165
166   Standard_Integer MasterRep;
167   switch (SC->MasterRepresentation())
168   {
169     case StepGeom_tpCartesian: MasterRep = 1; break;
170         case StepGeom_tpParameter: MasterRep = 2; break;
171         default: MasterRep = 0;
172   }
173
174   //gka 18.02.04 analysis for case when MasterRep = .Unspecified 
175   //and parameters are specified as CARTESIAN_POINT
176   Standard_Boolean isPoint = Standard_False;
177   if(MasterRep == 0 || (MasterRep == 2 && nbSel1 >1 && nbSel2 > 1)) {
178     Standard_Integer ii;
179     for(ii = 1; ii <= nbSel1; ii++)
180     {
181       if (!(theTrimSel1->Value(ii).CartesianPoint().IsNull()))
182       {
183         for(ii = 1; ii <= nbSel2; ii++)
184         {
185           if (!(theTrimSel2->Value(ii).CartesianPoint().IsNull()))
186           {
187             isPoint = Standard_True;
188             break;
189           }
190         }
191         break;
192       }
193         }
194   }
195   
196   //:o6 abv 18 Feb 99: computation of factor moved 
197   Standard_Real fact = 1., shift = 0.;
198   if (theSTEPCurve->IsKind(STANDARD_TYPE(StepGeom_Line))) {
199     const Handle(StepGeom_Line) theLine = 
200       Handle(StepGeom_Line)::DownCast(theSTEPCurve);
201     fact = theLine->Dir()->Magnitude() * UnitsMethods::LengthFactor();
202   }
203   else if (theSTEPCurve->IsKind(STANDARD_TYPE(StepGeom_Circle)) ||
204            theSTEPCurve->IsKind(STANDARD_TYPE(StepGeom_Ellipse))) {
205 //    if (trim1 > 2.1*M_PI || trim2 > 2.1*M_PI) fact = M_PI / 180.;
206     fact = UnitsMethods::PlaneAngleFactor();
207     //:p3 abv 23 Feb 99: shift on pi/2 on ellipse with R1 < R2
208     const Handle(StepGeom_Ellipse) ellipse = Handle(StepGeom_Ellipse)::DownCast(theSTEPCurve);
209     if ( !ellipse.IsNull() && ellipse->SemiAxis1() - ellipse->SemiAxis2() < 0. )
210       shift = 0.5 * M_PI;
211
212     // skl 04.02.2002 for OCC133: we can not make TrimmedCurve if
213     // there is no X-direction in StepGeom_Axis2Placement3d
214     const Handle(StepGeom_Conic) conic = Handle(StepGeom_Conic)::DownCast(theSTEPCurve);
215     // CKY 6-FEB-2004 for Airbus-MedialAxis : 
216     // this restriction does not apply for trimming by POINTS 
217     if(!conic.IsNull() && MasterRep != 1) {
218       const StepGeom_Axis2Placement a2p = conic->Position();
219       if(a2p.CaseNum(a2p.Value())==2) {
220         if( !a2p.Axis2Placement3d()->HasRefDirection() ) {
221           ////gka 18.02.04 analysis for case when MasterRep = .Unspecified 
222           //and parameters are specified as CARTESIAN_POINT
223           if(isPoint /*&& !MasterRep*/)
224             MasterRep =1;
225           else {
226             if ( SC->SenseAgreement() ) 
227               CC = new Geom_TrimmedCurve(theCurve, 0., 2.*M_PI, Standard_True);
228             else 
229               CC = new Geom_TrimmedCurve(theCurve, 2.*M_PI, 0., Standard_False);
230             return Standard_True;
231           }
232         }
233       }
234     }
235   }
236
237   Standard_Real trim1 = 0.;
238   Standard_Real trim2 = 0.;
239   Handle(StepGeom_CartesianPoint) TrimCP1, TrimCP2;
240   const Standard_Boolean FoundParam1 = ExtractParameter(theCurve, theTrimSel1, nbSel1, MasterRep, fact, shift, trim1);
241   const Standard_Boolean FoundParam2 = ExtractParameter(theCurve, theTrimSel2, nbSel2, MasterRep, fact, shift, trim2);
242
243   if (FoundParam1 && FoundParam2) {
244     const Standard_Real cf = theCurve->FirstParameter();
245     const Standard_Real cl = theCurve->LastParameter();
246     //: abv 09.04.99: S4136: bm2_ug_t4-B.stp #70610: protect against OutOfRange
247     if ( !theCurve->IsPeriodic() ) {
248       if ( trim1 < cf ) trim1 = cf;
249       else if ( trim1 > cl ) trim1 = cl;
250       if ( trim2 < cf ) trim2 = cf;
251       else if ( trim2 > cl ) trim2 = cl;
252     }
253     if (Abs(trim1 - trim2) < Precision::PConfusion()) {
254       if (theCurve->IsPeriodic()) {
255         ElCLib::AdjustPeriodic(cf,cl,Precision::PConfusion(),trim1,trim2);
256       }
257       else if (theCurve->IsClosed()) {
258         if (Abs(trim1 - cf) < Precision::PConfusion()) {
259           trim2 += cl;
260         }
261         else {
262           trim1 -= cl;
263         }
264       }
265       else {
266 //#ifdef DEBUG
267 //      cout << "Trimming Failed" << endl;
268 //#endif
269         return Standard_False;
270       }
271     }
272 //  CKY 16-DEC-1997 : USA60035 le texte de Part42 parle de degres
273 //    mais des systemes ecrivent en radians. Exploiter UnitsMethods
274 //:o6    trim1 = trim1 * fact;
275 //:o6    trim2 = trim2 * fact;
276     if ( SC->SenseAgreement() ) 
277       CC = new Geom_TrimmedCurve(theCurve, trim1, trim2, Standard_True);
278     else //:abv 29.09.00 PRO20362: reverse parameters in case of reversed curve
279       CC = new Geom_TrimmedCurve(theCurve, trim2, trim1, Standard_False);
280     return Standard_True;
281   }
282   return Standard_False;
283 }