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