1 // Created on: 1995-01-03
2 // Created by: Frederic MAUPAS
3 // Copyright (c) 1995-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
6 // This file is part of Open CASCADE Technology software library.
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
17 //:o0 abv 16.02.99: POLYLINE allowed as 3d curve of edge
18 //gka,abv 05.04.99: S4136: improving tolerance management, eliminate BRepAPI::Precision()
20 #include <BRep_Builder.hxx>
21 #include <BRep_Tool.hxx>
22 #include <BRepLib.hxx>
23 #include <BRepLib_MakeEdge.hxx>
24 #include <GCPnts_AbscissaPoint.hxx>
25 #include <Geom2d_Curve.hxx>
26 #include <Geom_CartesianPoint.hxx>
27 #include <Geom_Curve.hxx>
28 #include <Geom_Line.hxx>
29 #include <Geom_Surface.hxx>
30 #include <GeomAbs_Shape.hxx>
31 #include <GeomAdaptor_Curve.hxx>
35 #include <Precision.hxx>
36 #include <ShapeAnalysis_Curve.hxx>
37 #include <ShapeConstruct_Curve.hxx>
38 #include <StdFail_NotDone.hxx>
39 #include <StepGeom_CartesianPoint.hxx>
40 #include <StepGeom_Curve.hxx>
41 #include <StepGeom_Pcurve.hxx>
42 #include <StepGeom_Polyline.hxx>
43 #include <StepGeom_SurfaceCurve.hxx>
44 #include <StepRepr_DefinitionalRepresentation.hxx>
45 #include <StepShape_Edge.hxx>
46 #include <StepShape_EdgeCurve.hxx>
47 #include <StepShape_OrientedEdge.hxx>
48 #include <StepShape_Vertex.hxx>
49 #include <StepShape_VertexPoint.hxx>
50 #include <StepToGeom.hxx>
51 #include <StepToTopoDS.hxx>
52 #include <StepToTopoDS_GeometricTool.hxx>
53 #include <StepToTopoDS_NMTool.hxx>
54 #include <StepToTopoDS_Tool.hxx>
55 #include <StepToTopoDS_TranslateEdge.hxx>
56 #include <StepToTopoDS_TranslateVertex.hxx>
57 #include <TCollection_HAsciiString.hxx>
59 #include <TopoDS_Edge.hxx>
60 #include <TopoDS_Shape.hxx>
61 #include <TopoDS_Vertex.hxx>
62 #include <Transfer_TransientProcess.hxx>
63 #include <UnitsMethods.hxx>
64 #include <Standard_Failure.hxx>
66 //#include <StepGeom_Polyline.hxx>
67 //#include <TransferBRep.hxx>
69 // Used in I-DEAS-like STP processing (ssv; 15.11.2010)
71 // ============================================================================
72 // Method : DecodeMakeEdgeError
74 // ============================================================================
75 static void DecodeMakeEdgeError(const BRepLib_MakeEdge& ME,
76 const Handle(Standard_Transient)& orig,
77 const Handle(Geom_Curve)& myCurve,
78 const TopoDS_Vertex& V1,
79 const TopoDS_Vertex& V2,
80 const Standard_Real& U1,
81 const Standard_Real& U2,
82 StepToTopoDS_Tool& aTool,
83 const Handle(StepShape_TopologicalRepresentationItem)& /*tobind*/)
85 (void)U1, (void)U2; // avoid compiler warning
87 Handle(Transfer_TransientProcess) TP = aTool.TransientProcess();
90 cout << "------------------------------------" << endl;
91 cout << "MakeEdge Error : " << ME.Error()<<" - ";
95 case (BRepLib_EdgeDone): return;
96 case (BRepLib_PointProjectionFailed):
97 TP->AddFail(orig," Point Projection failed");
99 case (BRepLib_ParameterOutOfRange):
100 TP->AddFail(orig," Parameter Out Of Range");
102 case (BRepLib_DifferentPointsOnClosedCurve):
103 TP->AddFail(orig," Different Points on Closed Curve");
105 case (BRepLib_PointWithInfiniteParameter):
106 TP->AddFail(orig," Point with infinite Parameter");
108 case (BRepLib_DifferentsPointAndParameter):
109 if (!ShapeConstruct_Curve().AdjustCurve
110 (myCurve,BRep_Tool::Pnt(V1),BRep_Tool::Pnt(V2),Standard_True,Standard_True))
111 TP->AddFail(orig," Different Points and Parameters");
112 else TP->AddWarning(orig,"Different Points and Parameters, adjusted");
114 case (BRepLib_LineThroughIdenticPoints):
115 TP->AddFail(orig," Line through identic Points");
119 cout << "Original Type : " << orig->DynamicType() << endl;
120 cout << "3D Curve Type : " << myCurve->DynamicType() << endl;
121 cout << "First Parameter : " << U1 << endl;
122 gp_Pnt p1 = BRep_Tool::Pnt(V1);
123 // cout << "First Point : ";
124 cout << "First Vertex : "<<p1.X()<<" "<<p1.Y()<<" "<<p1.Z()<<" ";
125 cout << "Distance Point - Vertex : ";
126 Standard_Real d1 = p1.Distance(myCurve->Value(U1));
128 cout << "Last Parameter : " << U2 << endl;
129 gp_Pnt p2 = BRep_Tool::Pnt(V2);
130 // cout << "Last Point : ";
131 cout << "Last Vertex : "<<p2.X()<<" "<<p2.Y()<<" "<<p2.Z()<<" ";
132 cout << "Distance Point - Vertex : ";
133 Standard_Real d2 = BRep_Tool::Pnt(V2).Distance(myCurve->Value(U2));
138 // ============================================================================
139 // Method : StepToTopoDS_TranslateEdge::StepToTopoDS_TranslateEdge
140 // Purpose : Empty Constructor
141 // ============================================================================
143 static Handle(Geom_Curve) MakeCurve
144 (const Handle(StepGeom_Curve)& C1, const Handle(Transfer_TransientProcess) TP)
146 Handle(Geom_Curve) C2 = Handle(Geom_Curve)::DownCast (TP->FindTransient(C1));
147 if (!C2.IsNull()) return C2;
148 C2 = StepToGeom::MakeCurve (C1);
150 TP->BindTransient (C1,C2);
154 static TopoDS_Edge MakeEdge
155 (const Handle(Geom_Curve)& C3D,
156 const TopoDS_Vertex& V1, const TopoDS_Vertex& V2,
157 const Standard_Real U1, const Standard_Real U2)
161 B.MakeEdge (E,C3D,Precision::Confusion());
162 B.Add (E,V1); B.Add (E,V2);
163 B.UpdateVertex(V1, U1, E, 0.);
164 B.UpdateVertex(V2, U2, E, 0.);
168 // ============================================================================
169 // Method : StepToTopoDS_TranslateEdge::StepToTopoDS_TranslateEdge()
171 // ============================================================================
173 StepToTopoDS_TranslateEdge::StepToTopoDS_TranslateEdge()
175 done = Standard_False;
178 // ============================================================================
179 // Method : StepToTopoDS_TranslateEdge::StepToTopoDS_TranslateEdge()
180 // Purpose : Constructor with an Edge and a Tool
181 // ============================================================================
183 StepToTopoDS_TranslateEdge::StepToTopoDS_TranslateEdge(const Handle(StepShape_Edge)& E,
184 StepToTopoDS_Tool& T,
185 StepToTopoDS_NMTool& NMTool)
190 // ============================================================================
192 // Purpose : Init with an Edge and a Tool.
193 // This method builds an Edge With 2 Vertices and 2 Parameters.
194 // The Edge is always build like FORWARD (BRepLib_MakeEdge)
195 // ============================================================================
197 void StepToTopoDS_TranslateEdge::Init(const Handle(StepShape_Edge)& aEdge,
198 StepToTopoDS_Tool& aTool,
199 StepToTopoDS_NMTool& NMTool)
201 Handle(Transfer_TransientProcess) TP = aTool.TransientProcess();
203 Handle(StepShape_OrientedEdge) OE =
204 Handle(StepShape_OrientedEdge)::DownCast(aEdge);
205 Handle(StepShape_Edge) wEdge = aEdge;
206 if ( ! OE.IsNull() ) wEdge = OE->EdgeElement();
207 Handle(StepShape_EdgeCurve) EC = Handle(StepShape_EdgeCurve)::DownCast(wEdge);
209 if (aTool.IsBound(EC)) {
210 myResult = aTool.Find(EC);
211 if (BRep_Tool::Degenerated(TopoDS::Edge(myResult))) {
212 TP->AddWarning(EC,"Degenerated Edge in several faces : transferred for each face");
215 myError = StepToTopoDS_TranslateEdgeDone;
216 done = Standard_True;
217 //:S4136 B.SameRange(TopoDS::Edge(myResult), Standard_False); //:a5 abv 11 Feb 98
218 //:S4136 B.SameParameter(TopoDS::Edge(myResult), Standard_False);//:a5
223 // [BEGIN] Proceed with non-manifold cases (ssv; 12.11.2010)
224 if ( NMTool.IsActive() && NMTool.IsBound(EC) ) {
225 TopoDS_Shape existingShape = NMTool.Find(EC);
226 // Reverse shape's orientation if needed
227 if ( !OE->Orientation() )
228 existingShape.Reverse();
229 myResult = existingShape;
230 myError = StepToTopoDS_TranslateEdgeDone;
231 done = Standard_True;
234 // [END] Proceed with non-manifold cases (ssv; 12.11.2010)
236 // [BEGIN] Proceed with I-DEAS-like STP (ssv; 15.11.2010)
237 const Handle(TCollection_HAsciiString) anECName = EC->Name();
238 if ( NMTool.IsIDEASCase() && !anECName.IsNull() && !anECName->IsEmpty() &&
239 NMTool.IsBound(anECName->String()) ) {
240 TopoDS_Shape existingShape = NMTool.Find(anECName->String());
241 // Reverse shape's orientation if needed
242 if ( !OE->Orientation() )
243 existingShape.Reverse();
244 // Register Edge for final processing (I-DEAS case)
245 NMTool.RegisterNMEdge(existingShape);
246 myResult = existingShape;
247 myError = StepToTopoDS_TranslateEdgeDone;
248 done = Standard_True;
251 // [END] Proceed with I-DEAS-like STP (ssv; 15.11.2010)
255 Handle(StepGeom_Curve) C = EC->EdgeGeometry();
258 TP->AddFail(EC," Geom Curve in EdgeCurve is equal to 0");
259 myError = StepToTopoDS_TranslateEdgeOther;
260 done = Standard_False;
264 Handle(StepShape_Vertex) Vstart, Vend;
266 // -----------------------------------------------------------
267 // Extract the start and end Vertices corresponding to FORWARD
268 // (following the geometrical sense)
269 // -----------------------------------------------------------
271 Standard_Boolean EdgeCurveSameSense = EC->SameSense();
273 if (EdgeCurveSameSense) {
274 Vstart = EC->EdgeStart();
275 Vend = EC->EdgeEnd();
278 Vend = EC->EdgeStart();
279 Vstart = EC->EdgeEnd();
282 TopoDS_Vertex V1, V2;
284 StepToTopoDS_TranslateVertex myTranVertex1(Vstart, aTool, NMTool);
285 StepToTopoDS_TranslateVertex myTranVertex2(Vend, aTool, NMTool);
287 if (myTranVertex1.IsDone()) {
288 V1 = TopoDS::Vertex(myTranVertex1.Value());
289 V1.Orientation(TopAbs_FORWARD);
291 if (Vend == Vstart) {
293 V2.Orientation(TopAbs_REVERSED);
295 else if (myTranVertex2.IsDone()) {
296 V2 = TopoDS::Vertex(myTranVertex2.Value());
297 V2.Orientation(TopAbs_REVERSED);
299 done = Standard_True;
301 // ----------------------------------------------------------
302 // --- The EdgeCurve Geometry is of StepGeom_Curve Type
303 // --- It can be : * a Pcurve : no 3D curve is constructed
304 // --- * a Surface Curve, Intersection Curve
305 // --- or a Seam Curve
307 // ----------------------------------------------------------
309 if ( C->IsKind(STANDARD_TYPE(StepGeom_Pcurve))) {
311 //:S4136 B.UpdateEdge (E,preci);
315 else if (C->IsKind(STANDARD_TYPE(StepGeom_SurfaceCurve)) ) {
316 // For SeamCurve and IntersectionCurve types
317 // --- The Edge Geometry is a Surface Curve ---
318 // --- (3d + 2 Pcurve Or Surface) ---
319 Handle(StepGeom_SurfaceCurve) Sc =
320 Handle(StepGeom_SurfaceCurve)::DownCast(C);
321 Handle(StepGeom_Curve) C1 = Sc->Curve3d();
322 MakeFromCurve3D (C1,EC,Vend,Precision(), E,V1,V2 , aTool);
325 // --- The Edge Geometry is a Single 3d Curve ---
326 MakeFromCurve3D (C,EC,Vend,Precision(), E,V1,V2 , aTool);
328 // Force set flags SameRange and SameParameter to Standard_False
330 //:S4136 B.SameRange(E, Standard_False);
331 //:S4136 B.SameParameter(E, Standard_False);
334 // Bind Edge in NM tool (ssv; 15.11.2010)
335 if ( NMTool.IsActive() ) {
337 if ( NMTool.IsIDEASCase() && !anECName.IsNull() && !anECName->IsEmpty() )
338 NMTool.Bind(anECName->String(), E);
342 myError = StepToTopoDS_TranslateEdgeDone;
347 // ============================================================================
348 // Method : MakeFromCurve3D
349 // Purpose : case of a Curve 3D (alone or in SurfaceCurve)
350 // ============================================================================
352 // auxiliary function
353 //:e6 abv 16 Apr 98: ProSTEP TR8, r0601_sy.stp, #14907
354 static void GetCartesianPoints ( const Handle(StepShape_EdgeCurve)& EC,
355 gp_Pnt &P1, gp_Pnt &P2)
357 for ( Standard_Integer i=1; i<=2; i++ ) {
358 const Handle(StepShape_Vertex) V = ((i == 1) == EC->SameSense() ? EC->EdgeStart() : EC->EdgeEnd() );
359 const Handle(StepShape_VertexPoint) VP = Handle(StepShape_VertexPoint)::DownCast(V);
360 if ( VP.IsNull() ) continue;
361 const Handle(StepGeom_CartesianPoint) P = Handle(StepGeom_CartesianPoint)::DownCast(VP->VertexGeometry());
362 Handle(Geom_CartesianPoint) CP = StepToGeom::MakeCartesianPoint (P);
363 ( i==1 ? P1 : P2 ) = CP->Pnt();
367 // ============================================================================
368 // Method : StepToTopoDS_TranslateEdge::MakeFromCurve3D()
370 // ============================================================================
372 void StepToTopoDS_TranslateEdge::MakeFromCurve3D
373 (const Handle(StepGeom_Curve)& C3D, const Handle(StepShape_EdgeCurve)& EC,
374 const Handle(StepShape_Vertex)& Vend,
375 const Standard_Real preci, TopoDS_Edge& E,
376 TopoDS_Vertex& V1, TopoDS_Vertex& V2,
377 StepToTopoDS_Tool& aTool)
379 Handle(Transfer_TransientProcess) TP = aTool.TransientProcess();
380 Handle(Geom_Curve) C1 = MakeCurve(C3D,TP);
382 TP->AddFail(C3D," Make Geom_Curve (3D) failed");
383 myError = StepToTopoDS_TranslateEdgeOther;
384 done = Standard_False;
387 // -- Statistics -- -> No Warning message
388 aTool.AddContinuity (C1);
390 Standard_Real temp1,temp2, U1,U2;
392 gp_Pnt pv1 = BRep_Tool::Pnt(V1);
393 gp_Pnt pv2 = BRep_Tool::Pnt(V2);
396 gp_Pnt pnt1 = pv1, pnt2 = pv2;
397 if ( V1.IsSame ( V2 ) ) GetCartesianPoints ( EC, pnt1, pnt2 );
398 ShapeAnalysis_Curve sac;
399 temp1 = sac.Project (C1,pnt1,preci,pproj,U1,Standard_False);
400 temp2 = sac.Project (C1,pnt2,preci,pproj,U2,Standard_False);
402 if (!StepToTopoDS_GeometricTool::UpdateParam3d(C1, U1, U2, preci))
403 TP->AddWarning(C3D,"Update of 3D-Parameters has failed");
405 //:d5: instead of AdjustCurve above which is incorrect if U1 and U2 are not ends
406 GeomAdaptor_Curve aCA(C1);
407 gp_Pnt pU1 = aCA.Value ( U1 ), pU2 = aCA.Value ( U2 );
408 temp1 = pU1.Distance ( pv1 );
409 temp2 = pU2.Distance ( pv2 );
410 if ( temp1 > preci || temp2 > preci ) {
411 TP->AddWarning (C3D,"Poor result from projection vertex / curve 3d");
413 B.UpdateVertex ( V1, 1.000001*temp1 ); //:h6 abv 14 Jul 98: PRO8845 #2746: *=1.0001
414 B.UpdateVertex ( V2, 1.000001*temp2 ); //:h6
416 BRepLib_MakeEdge ME(C1, V1, V2, U1, U2);
419 B.Range ( E, U1, U2 ); // abv 14 Mar 00: trj3_pm1-ug.stp #91739, edge 2
422 if (ME.Error() == BRepLib_DifferentPointsOnClosedCurve) {
423 // The Edge could be closed and trimmed by 2 Different vertices
424 if (C1->IsClosed()) {
425 // Attention : topology updating
426 aTool.Bind (Vend,V1);
427 TopoDS_Shape aLocalShape = V1.Reversed();
428 V2 = TopoDS::Vertex(aLocalShape);
429 ME.Init(C1, V1, V2, U1, U2);
431 TP->AddWarning(EC, "Wrong topology corrected : Closed Edge with TWO different Vertices");
435 DecodeMakeEdgeError(ME, C3D, C1, V1, V2, U1, U2, aTool, EC);
436 E = MakeEdge (C1,V1,V2,U1,U2);
437 myError = StepToTopoDS_TranslateEdgeDone;
438 done = Standard_True;
443 // Then, this is should be coded as degenerated
444 // To be performed later !!!
445 myError = StepToTopoDS_TranslateEdgeDone;
446 // Bon, on la fait cette petite edge, mais faudra repasser
447 // pour l enlever ET FUSIONNER LES VERTEX, pour tout le shell !
448 // courbe trop petite pour etre mise -> fait planter
449 done = Standard_True;
450 if (!V1.IsSame(V2)) {
451 TP->AddFail(EC, "This edge has null arc length");
452 gp_Pnt P1 = BRep_Tool::Pnt(V1);
453 gp_Pnt P2 = BRep_Tool::Pnt(V2);
454 gp_Vec avec (P1,P2); gp_Dir adir (avec); gp_Lin alin (P1,adir);
455 C1 = new Geom_Line (alin);
456 U1 = 0.; U2 = P1.Distance(P2);
457 E = MakeEdge (C1,V1,V2,U1,U2);//,preci
460 TP->AddFail(EC,"NULL EDGE, SKIPPED");
467 DecodeMakeEdgeError(ME, C3D, C1, V1, V2, U1, U2, aTool, EC);
468 E = MakeEdge (C1,V1,V2,U1,U2);
469 myError = StepToTopoDS_TranslateEdgeDone;
470 done = Standard_True;
476 // ============================================================================
477 // Method : MakePCurve
478 // Purpose : Computes an individual pcurve (i.e. curve 2d)
479 // ============================================================================
480 Handle(Geom2d_Curve) StepToTopoDS_TranslateEdge::MakePCurve
481 (const Handle(StepGeom_Pcurve)& PCU, const Handle(Geom_Surface)& ConvSurf) const
483 Handle(Geom2d_Curve) C2d;
484 const Handle(StepRepr_DefinitionalRepresentation) DRI = PCU->ReferenceToCurve();
485 if( DRI.IsNull()) return C2d;
486 const Handle(StepGeom_Curve) StepCurve = Handle(StepGeom_Curve)::DownCast(DRI->ItemsValue(1));
489 C2d = StepToGeom::MakeCurve2d (StepCurve);
490 if (! C2d.IsNull()) {
491 // -- if the surface is a RectangularTrimmedSurface,
492 // -- send the BasisSurface.
493 C2d = UnitsMethods::DegreeToRadian(C2d, ConvSurf);
497 catch(Standard_Failure)
505 // ============================================================================
507 // Purpose : Returns the mapped edge
508 // ============================================================================
510 const TopoDS_Shape& StepToTopoDS_TranslateEdge::Value() const
512 StdFail_NotDone_Raise_if(!done,"");
516 // ============================================================================
518 // Purpose : Returns the error code
519 // ============================================================================
521 StepToTopoDS_TranslateEdgeError StepToTopoDS_TranslateEdge::Error() const