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