b311480e |
1 | // Created on: 1994-11-30 |
2 | // Created by: Frederic MAUPAS |
3 | // Copyright (c) 1994-1999 Matra Datavision |
973c2be1 |
4 | // Copyright (c) 1999-2014 OPEN CASCADE SAS |
b311480e |
5 | // |
973c2be1 |
6 | // This file is part of Open CASCADE Technology software library. |
b311480e |
7 | // |
d5f74e42 |
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 |
973c2be1 |
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. |
b311480e |
13 | // |
973c2be1 |
14 | // Alternatively, this file may be used under the terms of Open CASCADE |
15 | // commercial license or contractual agreement. |
7fd59977 |
16 | |
7fd59977 |
17 | |
42cf5bc1 |
18 | #include <Adaptor3d_CurveOnSurface.hxx> |
7fd59977 |
19 | #include <BRep_Tool.hxx> |
7fd59977 |
20 | #include <BRepAdaptor_Curve.hxx> |
21 | #include <BRepAdaptor_Surface.hxx> |
42cf5bc1 |
22 | #include <Geom2d_Line.hxx> |
23 | #include <Geom_BSplineCurve.hxx> |
24 | #include <Geom_Curve.hxx> |
25 | #include <Geom_Line.hxx> |
26 | #include <Geom_Plane.hxx> |
42cf5bc1 |
27 | #include <GeomToStep_MakeCurve.hxx> |
28 | #include <GeomToStep_MakeLine.hxx> |
29 | #include <gp_Vec.hxx> |
30 | #include <Interface_Static.hxx> |
31 | #include <StdFail_NotDone.hxx> |
28b505b2 |
32 | #include <StepData_Factors.hxx> |
b9fbc699 |
33 | #include <StepData_StepModel.hxx> |
42cf5bc1 |
34 | #include <StepGeom_Line.hxx> |
7fd59977 |
35 | #include <StepGeom_SeamCurve.hxx> |
36 | #include <StepGeom_SurfaceCurve.hxx> |
42cf5bc1 |
37 | #include <StepShape_EdgeCurve.hxx> |
38 | #include <StepShape_TopologicalRepresentationItem.hxx> |
39 | #include <StepShape_Vertex.hxx> |
7fd59977 |
40 | #include <TColgp_Array1OfPnt.hxx> |
42cf5bc1 |
41 | #include <TCollection_HAsciiString.hxx> |
7fd59977 |
42 | #include <TColStd_Array1OfInteger.hxx> |
42cf5bc1 |
43 | #include <TColStd_Array1OfReal.hxx> |
7fd59977 |
44 | #include <TopExp.hxx> |
42cf5bc1 |
45 | #include <TopExp_Explorer.hxx> |
46 | #include <TopoDS.hxx> |
47 | #include <TopoDS_Edge.hxx> |
42cf5bc1 |
48 | #include <TopoDSToStep_MakeStepEdge.hxx> |
49 | #include <TopoDSToStep_MakeStepVertex.hxx> |
50 | #include <TopoDSToStep_Tool.hxx> |
51 | #include <Transfer_FinderProcess.hxx> |
52 | #include <TransferBRep.hxx> |
7fd59977 |
53 | #include <TransferBRep_ShapeMapper.hxx> |
7ef1f9b7 |
54 | #include <BRepTools.hxx> |
55 | #include <ShapeAnalysis_Curve.hxx> |
7fd59977 |
56 | |
57 | // Processing of non-manifold topology (ssv; 11.11.2010) |
7fd59977 |
58 | // ---------------------------------------------------------------------------- |
59 | // Constructors |
60 | // ---------------------------------------------------------------------------- |
7fd59977 |
61 | TopoDSToStep_MakeStepEdge::TopoDSToStep_MakeStepEdge() |
d533dafb |
62 | : myError(TopoDSToStep_EdgeOther) |
7fd59977 |
63 | { |
64 | done = Standard_False; |
65 | } |
66 | |
67 | TopoDSToStep_MakeStepEdge::TopoDSToStep_MakeStepEdge |
68 | (const TopoDS_Edge& E, |
69 | TopoDSToStep_Tool& T, |
28b505b2 |
70 | const Handle(Transfer_FinderProcess)& FP, |
71 | const StepData_Factors& theLocalFactors) |
7fd59977 |
72 | { |
73 | done = Standard_False; |
28b505b2 |
74 | Init(E, T, FP, theLocalFactors); |
7fd59977 |
75 | } |
76 | |
77 | // ---------------------------------------------------------------------------- |
78 | // Method : Init |
79 | // Purpose : |
80 | // ---------------------------------------------------------------------------- |
81 | |
82 | void TopoDSToStep_MakeStepEdge::Init(const TopoDS_Edge& aEdge, |
83 | TopoDSToStep_Tool& aTool, |
28b505b2 |
84 | const Handle(Transfer_FinderProcess)& FP, |
85 | const StepData_Factors& theLocalFactors) |
7fd59977 |
86 | { |
87 | // ------------------------------------------------------------------ |
88 | // The edge is given with its relative orientation (i.e. in the wire) |
89 | // ------------------------------------------------------------------ |
90 | |
91 | aTool.SetCurrentEdge(aEdge); |
92 | |
93 | // [BEGIN] Processing non-manifold topology (ssv; 11.11.2010) |
b9fbc699 |
94 | Standard_Boolean isNMMode = |
95 | Handle(StepData_StepModel)::DownCast(FP->Model())->InternalParameters.WriteNonmanifold != 0; |
7fd59977 |
96 | if (isNMMode) { |
97 | Handle(StepShape_EdgeCurve) anEC; |
98 | Handle(TransferBRep_ShapeMapper) aSTEPMapper = TransferBRep::ShapeMapper(FP, aEdge); |
99 | if ( FP->FindTypedTransient(aSTEPMapper, STANDARD_TYPE(StepShape_EdgeCurve), anEC) ) { |
100 | // Non-manifold topology detected |
101 | myError = TopoDSToStep_EdgeDone; |
102 | myResult = anEC; |
103 | done = Standard_True; |
104 | return; |
105 | } |
106 | } |
107 | // [END] Processing non-manifold topology (ssv; 11.11.2010) |
108 | |
109 | if (aTool.IsBound(aEdge)) { |
110 | myError = TopoDSToStep_EdgeDone; |
111 | done = Standard_True; |
112 | myResult = aTool.Find(aEdge); |
113 | return; |
114 | } |
115 | |
116 | #define Nbpt 21 |
7fd59977 |
117 | Standard_Integer i; |
118 | Standard_Real U, U1, U2; |
119 | gp_Pnt P; |
120 | |
121 | Standard_Boolean isSeam = BRep_Tool::IsClosed(aEdge, aTool.CurrentFace()); |
122 | |
123 | //:i4 abv 02 Sep 98: ProSTEP TR8 Motor.rle f3 & f62: check that edge |
124 | // participates twice in the wires of the face before making it seam |
125 | // (else it can have two pcurves on the same surface being shared by |
126 | // two faces on that surface) |
127 | // This fix is necessary because sharing of surfaces is not preserved when |
128 | // writing faces to STEP (see TopoDSToSTEP_MakeStepFace) |
129 | if ( isSeam ) { |
130 | Standard_Integer count = 0; |
131 | TopExp_Explorer exp ( aTool.CurrentFace(), TopAbs_EDGE ); |
132 | for ( ; exp.More(); exp.Next() ) |
133 | if ( aEdge.IsSame ( exp.Current() ) ) count++; |
134 | if ( count < 2 ) isSeam = Standard_False; |
135 | } |
136 | |
137 | BRepAdaptor_Curve CA = BRepAdaptor_Curve(aEdge); |
138 | BRepAdaptor_Surface SA = BRepAdaptor_Surface(aTool.CurrentFace()); |
139 | |
140 | if (aEdge.Orientation() == TopAbs_INTERNAL || |
141 | aEdge.Orientation() == TopAbs_EXTERNAL ) { |
142 | Handle(TransferBRep_ShapeMapper) errShape = |
143 | new TransferBRep_ShapeMapper(aEdge); |
144 | FP->AddWarning(errShape, " Edge(internal/external) from Non Manifold Topology"); |
145 | myError = TopoDSToStep_NonManifoldEdge; |
146 | done = Standard_False; |
147 | return; |
148 | } |
149 | |
150 | // Vertices |
151 | |
152 | Handle(StepShape_Vertex) V1,V2; |
153 | Handle(StepShape_TopologicalRepresentationItem) Gpms2; |
154 | TopoDS_Vertex Vfirst, Vlast; |
155 | |
156 | TopExp::Vertices(aEdge,Vfirst, Vlast); |
157 | |
158 | TopoDSToStep_MakeStepVertex MkVertex; |
159 | |
28b505b2 |
160 | MkVertex.Init(Vfirst, aTool, FP, theLocalFactors); |
7fd59977 |
161 | if (MkVertex.IsDone()) |
162 | V1 = Handle(StepShape_Vertex)::DownCast(MkVertex.Value()); |
163 | else { |
164 | Handle(TransferBRep_ShapeMapper) errShape = |
165 | new TransferBRep_ShapeMapper(aEdge); |
166 | FP->AddWarning(errShape, " First Vertex of Edge not mapped"); |
167 | myError = TopoDSToStep_EdgeOther; |
168 | done = Standard_False; |
169 | return; |
170 | } |
171 | |
28b505b2 |
172 | MkVertex.Init(Vlast, aTool, FP, theLocalFactors); |
7fd59977 |
173 | if (MkVertex.IsDone()) |
174 | V2 = Handle(StepShape_Vertex)::DownCast(MkVertex.Value()); |
175 | else { |
176 | Handle(TransferBRep_ShapeMapper) errShape = |
177 | new TransferBRep_ShapeMapper(aEdge); |
178 | FP->AddWarning(errShape, " Last Vertex of Edge not mapped"); |
179 | myError = TopoDSToStep_EdgeOther; |
180 | done = Standard_False; |
181 | return; |
182 | } |
183 | |
184 | // --------------------------------------- |
185 | // Translate 3D representation of the Edge |
186 | // --------------------------------------- |
187 | |
188 | Handle(StepGeom_Curve) Gpms; |
189 | Handle(Geom_Curve) C = CA.Curve().Curve(); |
5e4f263d |
190 | |
7fd59977 |
191 | if (!C.IsNull()) { |
192 | C = Handle(Geom_Curve)::DownCast(C->Copy()); |
5e4f263d |
193 | gp_Trsf Tr1 = CA.Trsf(); |
194 | C->Transform(Tr1); |
7ef1f9b7 |
195 | // Special treatment is needed for very short edges based on periodic curves. |
196 | // Since edge in STEP does not store its parametric range, parameters are computed |
197 | // on import by projecting vertices on a curve, and for periodic curve this may |
198 | // lead to use of wrong part of the curve if end vertices are too close to each other |
199 | // (often whole curve is taken instead of its very small fragment). |
200 | if (C->IsPeriodic()) |
201 | { |
202 | Standard_Real dpar = CA.LastParameter() - CA.FirstParameter(); |
203 | if (dpar <= 0) |
204 | { |
205 | dpar += (ceil(fabs(dpar) / C->Period()) * C->Period()); |
206 | } |
207 | |
208 | // if range obtained from projection of vertices contradicts with range |
209 | // of the edge tnen vertices are swapped to keep results correct after import |
210 | // (see test de step_5 A1) |
211 | gp_Pnt aP1 = BRep_Tool::Pnt(Vfirst); |
212 | gp_Pnt aP2 = BRep_Tool::Pnt(Vlast); |
213 | gp_Pnt pproj; |
214 | ShapeAnalysis_Curve sac; |
215 | sac.Project (C, aP1, Tolerance(), pproj, U1, Standard_False); |
216 | sac.Project (C, aP2, Tolerance(), pproj, U2, Standard_False); |
217 | Standard_Real dU = U2 - U1; |
218 | if (dU <= 0) |
219 | { |
220 | dU += (ceil(fabs(dU) / C->Period()) * C->Period()); |
221 | } |
222 | if ((dU > Precision::PConfusion() && dU <= 0.1 * C->Period() && dpar > 0.5 * C->Period()) || |
223 | (dpar > Precision::PConfusion() && dpar <= 0.1 * C->Period() && dU > 0.5 * C->Period())) |
224 | { |
225 | std::swap (V1, V2); |
226 | } |
227 | |
228 | // If vertices overlap, we cut only needed part of the BSpline curve. |
229 | // Note that this method cannot be used for canonic curves |
230 | // (STEP does not support trimmed curves in AIC 514). |
231 | if (C->IsKind(STANDARD_TYPE(Geom_BSplineCurve))) |
232 | { |
233 | Standard_Real aTolV1 = BRep_Tool::Tolerance(Vfirst); |
234 | Standard_Real aTolV2 = BRep_Tool::Tolerance(Vlast); |
235 | gp_Pnt aP11 = CA.Value(CA.FirstParameter()); |
236 | gp_Pnt aP12 = CA.Value(CA.LastParameter()); |
237 | gp_Pnt aPm = CA.Value((CA.FirstParameter() + CA.LastParameter()) * 0.5); |
238 | Standard_Real aDist11 = aP11.Distance(aP12); |
239 | Standard_Real aDist1m = aP11.Distance(aPm); |
240 | Standard_Real aDist2m = aP12.Distance(aPm); |
241 | Standard_Real aDistMax = Max(Max(aDist1m, aDist2m), aDist11); |
242 | Standard_Boolean isSmallCurve = (aDistMax <= aTolV1 || aDistMax <= aTolV2); |
243 | if (BRepTools::Compare(Vfirst, Vlast) && isSmallCurve && dpar > Precision::PConfusion() && dpar <= 0.1 * C->Period()) |
244 | { |
245 | Handle(Geom_BSplineCurve) aBspl1 = Handle(Geom_BSplineCurve)::DownCast(C->Copy()); |
246 | aBspl1->Segment(CA.FirstParameter(), CA.LastParameter()); |
247 | C = aBspl1; |
248 | } |
249 | } |
250 | } |
251 | |
5e4f263d |
252 | |
28b505b2 |
253 | GeomToStep_MakeCurve MkCurve(C, theLocalFactors); |
7fd59977 |
254 | Gpms = MkCurve.Value(); |
255 | } |
256 | else { |
257 | |
258 | // ------------------------- |
259 | // a 3D Curve is constructed |
260 | // ------------------------- |
261 | |
0797d9d3 |
262 | #ifdef OCCT_DEBUG |
04232180 |
263 | std::cout << "Warning: TopoDSToStep_MakeStepEdge: edge without 3d curve; creating..." << std::endl; |
7fd59977 |
264 | #endif |
265 | if ((SA.GetType() == GeomAbs_Plane) && |
266 | (CA.GetType() == GeomAbs_Line)) { |
267 | U1 = CA.FirstParameter(); |
268 | U2 = CA.LastParameter(); |
269 | gp_Vec V = gp_Vec( CA.Value(U1), CA.Value(U2) ); |
270 | Handle(Geom_Line) L = |
271 | new Geom_Line(CA.Value(U1), gp_Dir(V)); |
28b505b2 |
272 | GeomToStep_MakeLine MkLine(L, theLocalFactors); |
7fd59977 |
273 | Gpms = MkLine.Value(); |
274 | } |
275 | else { |
276 | // To Be Optimized : create an approximated BSpline |
277 | // using GeomAPI_PointsToBSpline |
278 | TColgp_Array1OfPnt Points(1,Nbpt); |
279 | TColStd_Array1OfReal Knots(1,Nbpt); |
280 | TColStd_Array1OfInteger Mult(1,Nbpt); |
281 | U1 = CA.FirstParameter(); |
282 | U2 = CA.LastParameter(); |
283 | for ( i=1; i<=Nbpt; i++ ) { |
284 | U = U1 + (i-1)*(U2 - U1)/(Nbpt - 1); |
285 | P = CA.Value(U); |
286 | Points.SetValue(i,P); |
287 | Knots.SetValue(i,U); |
288 | Mult.SetValue(i,1); |
289 | } |
290 | //Points.SetValue(1, BRep_Tool::Pnt(Vfirst)); |
291 | //Points.SetValue(Nbpt, BRep_Tool::Pnt(Vlast)); |
292 | Mult.SetValue(1,2); |
293 | Mult.SetValue(Nbpt,2); |
c04c30b3 |
294 | Handle(Geom_Curve) Bs = |
7fd59977 |
295 | new Geom_BSplineCurve(Points, Knots, Mult, 1); |
28b505b2 |
296 | GeomToStep_MakeCurve MkCurve(Bs, theLocalFactors); |
7fd59977 |
297 | Gpms = MkCurve.Value(); |
298 | } |
299 | } |
300 | |
301 | // --------------------------------------------------------- |
302 | // Warning : if the edge is connected aGeom->Length = 2 |
303 | // otherwise = 1 ; |
304 | // and enumeration is pscrPcurveS2 or pscrPcurveS1 |
305 | // This is corrected in the Write File phases ! |
306 | // --------------------------------------------------------- |
307 | |
308 | //:abv 25.01.00 CAX-IF TRJ3 |
309 | // if PcurveMode is 1 (default), make surface_curve instead of simple 3d curve |
310 | if ( aTool.PCurveMode() != 0 ) { |
311 | |
312 | Handle(StepGeom_HArray1OfPcurveOrSurface) aGeom = |
313 | new StepGeom_HArray1OfPcurveOrSurface(1,2); |
314 | Handle(TCollection_HAsciiString) aName = new TCollection_HAsciiString(""); |
315 | |
316 | if (!isSeam) { |
317 | Handle(StepGeom_SurfaceCurve) SurfaceCurve = new StepGeom_SurfaceCurve; |
318 | SurfaceCurve->Init(aName, Gpms, aGeom, StepGeom_pscrPcurveS1); |
319 | Gpms = SurfaceCurve; |
320 | } |
321 | else { |
322 | Handle(StepGeom_SeamCurve) SeamCurve = new StepGeom_SeamCurve; |
323 | SeamCurve->Init(aName, Gpms, aGeom, StepGeom_pscrPcurveS1); |
324 | Gpms = SeamCurve; |
325 | } |
326 | } |
327 | |
328 | // Edge curve |
329 | Handle(StepShape_EdgeCurve) Epms = new StepShape_EdgeCurve; |
330 | Handle(TCollection_HAsciiString) aName = new TCollection_HAsciiString(""); |
331 | Epms->Init(aName, V1, V2, Gpms, Standard_True); |
332 | |
333 | aTool.Bind(aEdge, Epms); |
334 | myError = TopoDSToStep_EdgeDone; |
335 | myResult = Epms; |
336 | done = Standard_True; |
337 | return; |
338 | } |
339 | |
340 | // ---------------------------------------------------------------------------- |
341 | // Method : Value |
342 | // Purpose : |
343 | // ---------------------------------------------------------------------------- |
344 | |
345 | const Handle(StepShape_TopologicalRepresentationItem)& TopoDSToStep_MakeStepEdge::Value() const |
346 | { |
2d2b3d53 |
347 | StdFail_NotDone_Raise_if (!done, "TopoDSToStep_MakeStepEdge::Value() - no result"); |
7fd59977 |
348 | return myResult; |
349 | } |
350 | |
351 | // ---------------------------------------------------------------------------- |
352 | // Method : Error |
353 | // Purpose : |
354 | // ---------------------------------------------------------------------------- |
355 | |
356 | TopoDSToStep_MakeEdgeError TopoDSToStep_MakeStepEdge::Error() const |
357 | { |
358 | return myError; |
359 | } |