8013367c |
1 | // Created on: 2016-10-13 |
2 | // Created by: Alexander MALYSHEV |
3 | // Copyright (c) 1995-1999 Matra Datavision |
4 | // Copyright (c) 1999-2016 OPEN CASCADE SAS |
5 | // |
6 | // This file is part of Open CASCADE Technology software library. |
7 | // |
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. |
13 | // |
14 | // Alternatively, this file may be used under the terms of Open CASCADE |
15 | // commercial license or contractual agreement. |
16 | |
17 | // Include self. |
18 | #include <BRepOffset_MakeSimpleOffset.hxx> |
19 | |
20 | #include <Adaptor3d_CurveOnSurface.hxx> |
21 | #include <BRep_Builder.hxx> |
22 | #include <BRep_Tool.hxx> |
23 | #include <BRepLib.hxx> |
24 | #include <BRepLib_MakeEdge.hxx> |
25 | #include <BRepLib_MakeFace.hxx> |
26 | #include <BRepTools_Quilt.hxx> |
27 | #include <BRepAdaptor_HCurve2d.hxx> |
28 | #include <BRepAdaptor_HSurface.hxx> |
29 | #include <BRepAdaptor_Surface.hxx> |
30 | #include <BRepOffset_SimpleOffset.hxx> |
31 | #include <BRepTools_Modifier.hxx> |
32 | #include <Geom_TrimmedCurve.hxx> |
33 | #include <Geom2d_Line.hxx> |
34 | #include <GeomFill_Generator.hxx> |
35 | #include <Extrema_LocateExtPC.hxx> |
36 | #include <NCollection_List.hxx> |
37 | #include <ShapeAnalysis_FreeBounds.hxx> |
38 | #include <ShapeFix_Edge.hxx> |
39 | #include <TopExp.hxx> |
40 | #include <TopExp_Explorer.hxx> |
41 | #include <TopoDS_Edge.hxx> |
42 | #include <TopoDS_Face.hxx> |
43 | #include <TopoDS.hxx> |
44 | #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx> |
45 | #include <TopTools_ListIteratorOfListOfShape.hxx> |
46 | |
47 | |
48 | //============================================================================= |
49 | //function : BRepOffset_MakeSimpleOffset |
50 | //purpose : Constructor |
51 | //============================================================================= |
52 | BRepOffset_MakeSimpleOffset::BRepOffset_MakeSimpleOffset() |
8574e329 |
53 | : myOffsetValue(0.), |
54 | myTolerance(Precision::Confusion()), |
55 | myIsBuildSolid(Standard_False), |
8013367c |
56 | myMaxAngle(0.0), |
57 | myError(BRepOffsetSimple_OK), |
58 | myIsDone(Standard_False) |
59 | { |
60 | myReShape = new ShapeBuild_ReShape(); |
61 | } |
62 | |
63 | //============================================================================= |
64 | //function : BRepOffset_MakeSimpleOffset |
65 | //purpose : Constructor |
66 | //============================================================================= |
67 | BRepOffset_MakeSimpleOffset::BRepOffset_MakeSimpleOffset(const TopoDS_Shape& theInputShape, |
68 | const Standard_Real theOffsetValue) |
69 | : myInputShape(theInputShape), |
70 | myOffsetValue(theOffsetValue), |
8574e329 |
71 | myTolerance(Precision::Confusion()), |
8013367c |
72 | myIsBuildSolid(Standard_False), |
73 | myMaxAngle(0.0), |
74 | myError(BRepOffsetSimple_OK), |
75 | myIsDone(Standard_False) |
76 | { |
77 | myReShape = new ShapeBuild_ReShape(); |
78 | } |
79 | |
80 | //============================================================================= |
81 | //function : Initialize |
82 | //purpose : |
83 | //============================================================================= |
84 | void BRepOffset_MakeSimpleOffset::Initialize(const TopoDS_Shape& theInputShape, |
85 | const Standard_Real theOffsetValue) |
86 | { |
87 | myInputShape = theInputShape; |
88 | myOffsetValue = theOffsetValue; |
89 | Clear(); |
90 | } |
91 | |
92 | //============================================================================= |
93 | //function : GetErrorMessage |
94 | //purpose : |
95 | //============================================================================= |
96 | TCollection_AsciiString BRepOffset_MakeSimpleOffset::GetErrorMessage() const |
97 | { |
98 | TCollection_AsciiString anError = ""; |
99 | |
100 | if (myError == BRepOffsetSimple_NullInputShape) |
101 | { |
102 | anError = "Null input shape"; |
103 | return anError; |
104 | } |
105 | else if (myError == BRepOffsetSimple_ErrorOffsetComputation) |
106 | { |
107 | anError = "Error during offset construction"; |
108 | return anError; |
109 | } |
110 | else if (myError == BRepOffsetSimple_ErrorWallFaceComputation) |
111 | { |
112 | anError = "Error during building wall face"; |
113 | return anError; |
114 | } |
115 | else if (myError == BRepOffsetSimple_ErrorInvalidNbShells) |
116 | { |
117 | anError = "Result contains two or more shells"; |
118 | return anError; |
119 | } |
120 | else if (myError == BRepOffsetSimple_ErrorNonClosedShell) |
121 | { |
122 | anError = "Result shell is not closed"; |
123 | return anError; |
124 | } |
125 | |
126 | return anError; |
127 | } |
128 | |
129 | //============================================================================= |
130 | //function : Clear |
131 | //purpose : |
132 | //============================================================================= |
133 | void BRepOffset_MakeSimpleOffset::Clear() |
134 | { |
135 | myIsDone = Standard_False; |
136 | myError = BRepOffsetSimple_OK; |
137 | myMaxAngle = 0.0; |
138 | myMapVE.Clear(); |
139 | myReShape->Clear(); // Clear possible stored modifications. |
140 | } |
141 | |
142 | //============================================================================= |
143 | //function : GetSafeOffset |
144 | //purpose : |
145 | //============================================================================= |
146 | Standard_Real BRepOffset_MakeSimpleOffset::GetSafeOffset(const Standard_Real theExpectedToler) |
147 | { |
148 | if (myInputShape.IsNull()) |
149 | return 0.0; // Input shape is null. |
150 | |
151 | // Compute max angle in faces junctions. |
152 | if (myMaxAngle == 0.0) // Non-initialized. |
153 | ComputeMaxAngle(); |
154 | |
155 | Standard_Real aMaxTol = 0.0; |
156 | aMaxTol = BRep_Tool::MaxTolerance(myInputShape, TopAbs_VERTEX); |
157 | |
158 | const Standard_Real anExpOffset = Max((theExpectedToler - aMaxTol) / (2.0 * myMaxAngle), |
159 | 0.0); // Minimal distance can't be lower than 0.0. |
160 | return anExpOffset; |
161 | } |
162 | |
163 | //============================================================================= |
164 | //function : Perform |
165 | //purpose : |
166 | //============================================================================= |
167 | void BRepOffset_MakeSimpleOffset::Perform() |
168 | { |
169 | // Clear result of previous computations. |
170 | Clear(); |
171 | |
172 | // Check shape existence. |
173 | if (myInputShape.IsNull()) |
174 | { |
175 | myError = BRepOffsetSimple_NullInputShape; |
176 | return; |
177 | } |
178 | |
179 | if (myMaxAngle == 0.0) // Non-initialized. |
180 | ComputeMaxAngle(); |
181 | |
182 | myBuilder.Init(myInputShape); |
8574e329 |
183 | Handle(BRepOffset_SimpleOffset) aMapper = new BRepOffset_SimpleOffset(myInputShape, myOffsetValue, myTolerance); |
8013367c |
184 | myBuilder.Perform(aMapper); |
185 | |
186 | if (!myBuilder.IsDone()) |
187 | { |
188 | myError = BRepOffsetSimple_ErrorOffsetComputation; |
189 | return; |
190 | } |
191 | |
192 | myResShape = myBuilder.ModifiedShape(myInputShape); |
193 | |
194 | // Fix degeneracy. Degenerated edge should be mapped to the degenerated. |
195 | BRep_Builder aBB; |
196 | TopExp_Explorer anExpSE(myInputShape, TopAbs_EDGE); |
197 | for(; anExpSE.More(); anExpSE.Next()) |
198 | { |
199 | const TopoDS_Edge & aCurrEdge = TopoDS::Edge(anExpSE.Current()); |
200 | |
201 | if (!BRep_Tool::Degenerated(aCurrEdge)) |
202 | continue; |
203 | |
204 | const TopoDS_Edge & anEdge = TopoDS::Edge(myBuilder.ModifiedShape(aCurrEdge)); |
205 | aBB.Degenerated(anEdge, Standard_True); |
206 | } |
207 | |
208 | // Restore walls for solid. |
209 | if (myIsBuildSolid && !BuildMissingWalls()) |
210 | return; |
211 | |
212 | myIsDone = Standard_True; |
213 | } |
214 | |
215 | //============================================================================= |
216 | //function : tgtfaces |
217 | //purpose : check the angle at the border between two squares. |
218 | // Two shares should have a shared front edge. |
219 | //============================================================================= |
220 | static void tgtfaces(const TopoDS_Edge& Ed, |
221 | const TopoDS_Face& F1, |
222 | const TopoDS_Face& F2, |
223 | const Standard_Boolean couture, |
224 | Standard_Real& theResAngle) |
225 | { |
226 | // Check that pcurves exist on both faces of edge. |
227 | Standard_Real aFirst,aLast; |
228 | Handle(Geom2d_Curve) aCurve; |
229 | aCurve = BRep_Tool::CurveOnSurface(Ed,F1,aFirst,aLast); |
230 | if(aCurve.IsNull()) |
231 | return; |
232 | aCurve = BRep_Tool::CurveOnSurface(Ed,F2,aFirst,aLast); |
233 | if(aCurve.IsNull()) |
234 | return; |
235 | |
236 | Standard_Real u; |
237 | TopoDS_Edge E = Ed; |
238 | BRepAdaptor_Surface aBAS1(F1,Standard_False); |
239 | BRepAdaptor_Surface aBAS2(F2,Standard_False); |
240 | |
241 | Handle(BRepAdaptor_HSurface) HS1 = new BRepAdaptor_HSurface (aBAS1); |
242 | Handle(BRepAdaptor_HSurface) HS2; |
243 | if(couture) HS2 = HS1; |
244 | else HS2 = new BRepAdaptor_HSurface(aBAS2); |
245 | //case when edge lies on the one face |
246 | |
247 | E.Orientation(TopAbs_FORWARD); |
248 | BRepAdaptor_Curve2d C2d1(E, F1); |
249 | if(couture) E.Orientation(TopAbs_REVERSED); |
250 | BRepAdaptor_Curve2d C2d2(E,F2); |
251 | |
252 | Standard_Boolean rev1 = (F1.Orientation() == TopAbs_REVERSED); |
253 | Standard_Boolean rev2 = (F2.Orientation() == TopAbs_REVERSED); |
254 | Standard_Real f,l,eps; |
255 | BRep_Tool::Range(E,f,l); |
256 | Extrema_LocateExtPC ext; |
257 | |
258 | eps = (l - f) / 100.0; |
259 | f += eps; // to avoid calculations on |
260 | l -= eps; // points of pointed squares. |
261 | gp_Pnt2d p; |
262 | gp_Pnt pp1,pp2;//,PP; |
263 | gp_Vec du1, dv1; |
264 | gp_Vec du2, dv2; |
265 | gp_Vec d1,d2; |
266 | Standard_Real norm; |
267 | |
268 | const Standard_Integer NBPNT = 23; |
269 | for(Standard_Integer i = 0; i <= NBPNT; i++) |
270 | { |
271 | // First suppose that this is sameParameter |
272 | u = f + (l - f) * i / NBPNT; |
273 | |
274 | // take derivatives of surfaces at the same u, and compute normals |
275 | C2d1.D0(u,p); |
276 | HS1->D1 (p.X(), p.Y(), pp1, du1, dv1); |
277 | d1 = (du1.Crossed(dv1)); |
278 | norm = d1.Magnitude(); |
279 | if (norm > 1.e-12) d1 /= norm; |
280 | else continue; // skip degenerated point |
281 | if(rev1) d1.Reverse(); |
282 | |
283 | C2d2.D0(u,p); |
284 | HS2->D1 (p.X(), p.Y(), pp2, du2, dv2); |
285 | d2 = (du2.Crossed(dv2)); |
286 | norm = d2.Magnitude(); |
287 | if (norm > 1.e-12) d2 /= norm; |
288 | else continue; // skip degenerated point |
289 | if(rev2) d2.Reverse(); |
290 | |
291 | // Compute angle. |
292 | Standard_Real aCurrentAng = d1.Angle(d2); |
293 | |
294 | theResAngle = Max(theResAngle, aCurrentAng); |
295 | } |
296 | } |
297 | |
298 | //============================================================================= |
299 | // function : ComputeMaxAngleOnShape |
300 | // purpose : Code the regularities on all edges of the shape, boundary of |
301 | // two faces that do not have it. |
302 | //============================================================================= |
303 | static void ComputeMaxAngleOnShape(const TopoDS_Shape& S, |
304 | Standard_Real& theResAngle) |
305 | { |
306 | TopTools_IndexedDataMapOfShapeListOfShape M; |
307 | TopExp::MapShapesAndAncestors(S,TopAbs_EDGE,TopAbs_FACE,M); |
308 | TopTools_ListIteratorOfListOfShape It; |
309 | TopExp_Explorer Ex; |
310 | TopoDS_Face F1,F2; |
311 | Standard_Boolean found, couture; |
312 | for(Standard_Integer i = 1; i <= M.Extent(); i++) |
313 | { |
314 | TopoDS_Edge E = TopoDS::Edge(M.FindKey(i)); |
315 | found = Standard_False; couture = Standard_False; |
316 | F1.Nullify(); |
317 | for(It.Initialize(M.FindFromIndex(i));It.More() && !found;It.Next()) |
318 | { |
319 | if(F1.IsNull()) { F1 = TopoDS::Face(It.Value()); } |
320 | else |
321 | { |
322 | if(!F1.IsSame(TopoDS::Face(It.Value()))) |
323 | { |
324 | found = Standard_True; |
325 | F2 = TopoDS::Face(It.Value()); |
326 | } |
327 | } |
328 | } |
329 | if (!found && !F1.IsNull()){//is it a sewing edge? |
330 | TopAbs_Orientation orE = E.Orientation(); |
331 | TopoDS_Edge curE; |
332 | for(Ex.Init(F1,TopAbs_EDGE);Ex.More() && !found;Ex.Next()){ |
333 | curE= TopoDS::Edge(Ex.Current()); |
334 | if(E.IsSame(curE) && orE != curE.Orientation()) |
335 | { |
336 | found = Standard_True; |
337 | couture = Standard_True; |
338 | F2 = F1; |
339 | } |
340 | } |
341 | } |
342 | if(found) |
343 | { |
344 | if(BRep_Tool::Continuity(E,F1,F2)<=GeomAbs_C0) |
345 | { |
346 | try |
347 | { |
348 | tgtfaces(E, F1, F2, couture, theResAngle); |
349 | } |
350 | catch(Standard_Failure) |
351 | { |
352 | } |
353 | } |
354 | } |
355 | } |
356 | } |
357 | |
358 | //============================================================================= |
359 | //function : ComputeMaxAngle |
360 | //purpose : Computes max angle in faces junction |
361 | //============================================================================= |
362 | void BRepOffset_MakeSimpleOffset::ComputeMaxAngle() |
363 | { |
364 | ComputeMaxAngleOnShape(myInputShape, myMaxAngle); |
365 | } |
366 | |
367 | //============================================================================= |
368 | //function : BuildMissingWalls |
369 | //purpose : Builds walls to the result solid. |
370 | //============================================================================= |
371 | Standard_Boolean BRepOffset_MakeSimpleOffset::BuildMissingWalls() |
372 | { |
373 | // Internal list of new faces. |
374 | TopoDS_Compound aNewFaces; |
375 | BRep_Builder aBB; |
376 | aBB.MakeCompound(aNewFaces); |
377 | |
378 | // Compute outer bounds of original shape. |
379 | ShapeAnalysis_FreeBounds aFB(myInputShape); |
380 | const TopoDS_Compound& aFreeWires = aFB.GetClosedWires(); |
381 | |
382 | // Build linear faces on each edge and its image. |
383 | TopExp_Explorer anExpCW(aFreeWires,TopAbs_WIRE); |
384 | for(; anExpCW.More() ; anExpCW.Next()) |
385 | { |
386 | const TopoDS_Wire& aCurWire = TopoDS::Wire(anExpCW.Current()); |
387 | |
388 | // Iterate over outer edges in outer wires. |
389 | TopExp_Explorer anExpWE(aCurWire, TopAbs_EDGE); |
390 | for(; anExpWE.More() ; anExpWE.Next()) |
391 | { |
392 | const TopoDS_Edge& aCurEdge = TopoDS::Edge(anExpWE.Current()); |
393 | |
394 | TopoDS_Face aNewFace = BuildWallFace(aCurEdge); |
395 | |
396 | if (aNewFace.IsNull()) |
397 | { |
398 | myError = BRepOffsetSimple_ErrorWallFaceComputation; |
399 | return Standard_False; |
400 | } |
401 | |
402 | aBB.Add(aNewFaces, aNewFace); |
403 | } |
404 | } |
405 | |
406 | // Update edges from wall faces. |
407 | ShapeFix_Edge aSFE; |
408 | aSFE.SetContext(myReShape); |
409 | TopExp_Explorer anExpCE(aNewFaces, TopAbs_EDGE); |
410 | for ( ; anExpCE.More() ; anExpCE.Next()) |
411 | { |
412 | // Fix same parameter and same range flags. |
413 | const TopoDS_Edge& aCurrEdge = TopoDS::Edge(anExpCE.Current()); |
414 | aSFE.FixSameParameter(aCurrEdge); |
415 | } |
416 | |
417 | // Update result to be compound. |
418 | TopoDS_Compound aResCompound; |
419 | aBB.MakeCompound(aResCompound); |
420 | |
421 | // Add old faces the result. |
422 | TopExp_Explorer anExpSF(myInputShape, TopAbs_FACE); |
423 | for ( ; anExpSF.More() ; anExpSF.Next()) |
424 | aBB.Add(aResCompound, anExpSF.Current()); |
425 | |
426 | // Add new faces the result. |
427 | anExpSF.Init(myResShape, TopAbs_FACE); |
428 | for ( ; anExpSF.More() ; anExpSF.Next()) |
429 | aBB.Add(aResCompound, anExpSF.Current()); |
430 | |
431 | // Add wall faces to the result. |
432 | TopExp_Explorer anExpCF(aNewFaces, TopAbs_FACE); |
433 | for ( ; anExpCF.More() ; anExpCF.Next()) |
434 | { |
435 | const TopoDS_Face& aF = TopoDS::Face(anExpCF.Current()); |
436 | aBB.Add(aResCompound, aF); |
437 | } |
438 | |
439 | // Apply stored modifications. |
440 | aResCompound = TopoDS::Compound(myReShape->Apply(aResCompound)); |
441 | |
442 | // Create result shell. |
443 | BRepTools_Quilt aQuilt; |
444 | aQuilt.Add(aResCompound); |
445 | TopoDS_Shape aShells = aQuilt.Shells(); |
446 | |
447 | TopExp_Explorer anExpSSh(aShells, TopAbs_SHELL); |
448 | TopoDS_Shell aResShell; |
449 | for ( ; anExpSSh.More() ; anExpSSh.Next() ) |
450 | { |
451 | if (!aResShell.IsNull()) |
452 | { |
453 | // Shell is not null -> explorer contains two or more shells. |
454 | myError = BRepOffsetSimple_ErrorInvalidNbShells; |
455 | return Standard_False; |
456 | } |
457 | aResShell = TopoDS::Shell(anExpSSh.Current()); |
458 | } |
459 | |
460 | if (!BRep_Tool::IsClosed(aResShell)) |
461 | { |
462 | myError = BRepOffsetSimple_ErrorNonClosedShell; |
463 | return Standard_False; |
464 | } |
465 | |
466 | // Create result solid. |
467 | TopoDS_Solid aResSolid; |
468 | aBB.MakeSolid(aResSolid); |
469 | aBB.Add(aResSolid, aResShell); |
470 | myResShape = aResSolid; |
471 | |
472 | return Standard_True; |
473 | } |
474 | |
475 | //============================================================================= |
476 | //function : BuildWallFace |
477 | //purpose : |
478 | //============================================================================= |
479 | TopoDS_Face BRepOffset_MakeSimpleOffset::BuildWallFace(const TopoDS_Edge& theOrigEdge) |
480 | { |
481 | TopoDS_Face aResFace; |
482 | |
483 | // Get offset edge. offset edge is revered to create correct wire. |
484 | TopoDS_Edge aNewEdge = TopoDS::Edge(myBuilder.ModifiedShape(theOrigEdge)); |
485 | aNewEdge.Orientation(TopAbs_REVERSED); |
486 | |
487 | TopoDS_Vertex aNewV1, aNewV2; |
488 | TopExp::Vertices(aNewEdge, aNewV1, aNewV2); |
489 | |
490 | // Wire contour is: |
491 | // theOrigEdge (forcible forward) -> wall1 -> aNewEdge (forcible reversed) -> wall2 |
492 | // Firstly it is necessary to create copy of original shape with forward direction. |
493 | // This simplifies walls creation. |
494 | TopoDS_Edge anOrigCopy = theOrigEdge; |
495 | anOrigCopy.Orientation(TopAbs_FORWARD); |
496 | TopoDS_Vertex aV1, aV2; |
497 | TopExp::Vertices(anOrigCopy, aV1, aV2); |
498 | |
499 | // To simplify work with map. |
500 | TopoDS_Vertex aForwardV1 = TopoDS::Vertex(aV1.Oriented(TopAbs_FORWARD)); |
501 | TopoDS_Vertex aForwardV2 = TopoDS::Vertex(aV2.Oriented(TopAbs_FORWARD)); |
502 | |
503 | // Check existence of edges in stored map: Edge1 |
504 | TopoDS_Edge aWall1; |
505 | if (myMapVE.IsBound(aForwardV2)) |
506 | { |
507 | // Edge exists - get it from map. |
508 | aWall1 = myMapVE(aForwardV2); |
509 | } |
510 | else |
511 | { |
512 | // Edge does not exist - create it and add to the map. |
513 | BRepLib_MakeEdge aME1(TopoDS::Vertex(aV2.Oriented(TopAbs_FORWARD)), |
514 | TopoDS::Vertex(aNewV2.Oriented(TopAbs_REVERSED))); |
515 | if (!aME1.IsDone()) |
516 | return aResFace; |
517 | aWall1 = aME1.Edge(); |
518 | |
519 | myMapVE.Bind(aForwardV2, aWall1); |
520 | } |
521 | |
522 | // Check existence of edges in stored map: Edge2 |
523 | TopoDS_Edge aWall2; |
524 | if (myMapVE.IsBound(aForwardV1)) |
525 | { |
526 | // Edge exists - get it from map. |
527 | aWall2 = TopoDS::Edge(myMapVE(aForwardV1).Oriented(TopAbs_REVERSED)); |
528 | } |
529 | else |
530 | { |
531 | // Edge does not exist - create it and add to the map. |
532 | BRepLib_MakeEdge aME2(TopoDS::Vertex(aV1.Oriented(TopAbs_FORWARD)), |
533 | TopoDS::Vertex(aNewV1.Oriented(TopAbs_REVERSED))); |
534 | if (!aME2.IsDone()) |
535 | return aResFace; |
536 | aWall2 = aME2.Edge(); |
537 | |
538 | myMapVE.Bind(aForwardV1, aWall2); |
539 | |
540 | // Orient it in reversed direction. |
541 | aWall2.Orientation(TopAbs_REVERSED); |
542 | } |
543 | |
544 | BRep_Builder aBB; |
545 | |
546 | TopoDS_Wire aWire; |
547 | aBB.MakeWire(aWire); |
548 | aBB.Add(aWire, anOrigCopy); |
549 | aBB.Add(aWire, aWall1); |
550 | aBB.Add(aWire, aNewEdge); |
551 | aBB.Add(aWire, aWall2); |
552 | |
553 | // Build 3d curves on wire |
554 | BRepLib::BuildCurves3d( aWire ); |
555 | |
556 | // Try to build using simple planar approach. |
557 | TopoDS_Face aF; |
558 | try |
559 | { |
560 | // Call of face maker is wrapped by try/catch since it generates exceptions sometimes. |
561 | BRepLib_MakeFace aFM(aWire, Standard_True); |
562 | if (aFM.IsDone()) |
563 | aF = aFM.Face(); |
564 | } |
565 | catch(Standard_Failure) |
566 | { |
567 | } |
568 | |
569 | if (aF.IsNull()) // Exception in face maker or result is not computed. |
570 | { |
571 | // Build using thrusections. |
572 | Standard_Boolean ToReverse = Standard_False; |
573 | Standard_Real fpar, lpar, fparOE, lparOE; |
574 | Handle(Geom_Curve) EdgeCurve = BRep_Tool::Curve(theOrigEdge, fpar, lpar); |
575 | Handle(Geom_TrimmedCurve) TrEdgeCurve = new Geom_TrimmedCurve( EdgeCurve, fpar, lpar ); |
576 | Handle(Geom_Curve) OffsetCurve = BRep_Tool::Curve(aNewEdge, fparOE, lparOE); |
577 | Handle(Geom_TrimmedCurve) TrOffsetCurve = new Geom_TrimmedCurve( OffsetCurve, fparOE, lparOE ); |
578 | |
579 | GeomFill_Generator ThrusecGenerator; |
580 | ThrusecGenerator.AddCurve( TrEdgeCurve ); |
581 | ThrusecGenerator.AddCurve( TrOffsetCurve ); |
582 | ThrusecGenerator.Perform( Precision::PConfusion() ); |
583 | Handle(Geom_Surface) theSurf = ThrusecGenerator.Surface(); |
584 | //theSurf = new Geom_SurfaceOfLinearExtrusion( TrOffsetCurve, OffsetDir ); |
585 | Standard_Real Uf, Ul, Vf, Vl; |
586 | theSurf->Bounds(Uf, Ul, Vf, Vl); |
587 | TopLoc_Location Loc; |
588 | Handle(Geom2d_Line) EdgeLine2d, OELine2d, aLine2d, aLine2d2; |
589 | EdgeLine2d = new Geom2d_Line(gp_Pnt2d(0., Vf), gp_Dir2d(1., 0.)); |
590 | aBB.UpdateEdge(theOrigEdge, EdgeLine2d, theSurf, Loc, Precision::Confusion()); |
591 | OELine2d = new Geom2d_Line(gp_Pnt2d(0., Vl), gp_Dir2d(1., 0.)); |
592 | aBB.UpdateEdge(aNewEdge, OELine2d, theSurf, Loc, Precision::Confusion()); |
593 | Standard_Real UonV1 = (ToReverse)? Ul : Uf; |
594 | Standard_Real UonV2 = (ToReverse)? Uf : Ul; |
595 | aLine2d = new Geom2d_Line(gp_Pnt2d(UonV2, 0.), gp_Dir2d(0., 1.)); |
596 | aLine2d2 = new Geom2d_Line(gp_Pnt2d(UonV1, 0.), gp_Dir2d(0., 1.)); |
597 | if (aWall1.IsSame(aWall2)) |
598 | { |
599 | aBB.UpdateEdge(aWall1, aLine2d, aLine2d2, theSurf, Loc, Precision::Confusion()); |
600 | Handle(Geom_Curve) BSplC34 = theSurf->UIso( Uf ); |
601 | aBB.UpdateEdge(aWall1, BSplC34, Precision::Confusion()); |
602 | aBB.Range(aWall1, Vf, Vl); |
603 | } |
604 | else |
605 | { |
606 | aBB.SameParameter(aWall1, Standard_False); |
607 | aBB.SameRange(aWall1, Standard_False); |
608 | aBB.SameParameter(aWall2, Standard_False); |
609 | aBB.SameRange(aWall2, Standard_False); |
610 | aBB.UpdateEdge(aWall1, aLine2d, theSurf, Loc, Precision::Confusion()); |
611 | aBB.Range(aWall1, theSurf, Loc, Vf, Vl); |
612 | aBB.UpdateEdge(aWall2, aLine2d2, theSurf, Loc, Precision::Confusion()); |
613 | aBB.Range(aWall2, theSurf, Loc, Vf, Vl); |
614 | Handle(Geom_Curve) BSplC3 = theSurf->UIso( UonV2 ); |
615 | aBB.UpdateEdge(aWall1, BSplC3, Precision::Confusion()); |
616 | aBB.Range(aWall1, Vf, Vl, Standard_True); //only for 3d curve |
617 | Handle(Geom_Curve) BSplC4 = theSurf->UIso( UonV1 ); |
618 | aBB.UpdateEdge(aWall2, BSplC4, Precision::Confusion()); |
619 | aBB.Range(aWall2, Vf, Vl, Standard_True); //only for 3d curve |
620 | } |
621 | |
622 | aF = BRepLib_MakeFace(theSurf, aWire); |
623 | |
624 | } |
625 | |
626 | return aF; |
627 | } |
628 | |
629 | //============================================================================= |
630 | //function : Generated |
631 | //purpose : |
632 | //============================================================================= |
633 | const TopoDS_Shape BRepOffset_MakeSimpleOffset::Generated(const TopoDS_Shape& theShape) const |
634 | { |
635 | // Shape generated by modification. |
636 | TopoDS_Shape aRes; |
637 | aRes = myBuilder.ModifiedShape(theShape); |
638 | |
639 | if (aRes.IsNull()) |
640 | return aRes; |
641 | |
642 | // Shape modifications obtained in scope of shape healing. |
643 | aRes = myReShape->Apply(aRes); |
644 | |
645 | return aRes; |
646 | } |
647 | |
648 | //============================================================================= |
649 | //function : Modified |
650 | //purpose : |
651 | //============================================================================= |
652 | const TopoDS_Shape BRepOffset_MakeSimpleOffset::Modified(const TopoDS_Shape& theShape) const |
653 | { |
654 | TopoDS_Shape aRes, anEmptyShape; |
655 | |
656 | // Get modification status and new shape. |
657 | Standard_Integer aModStatus = myReShape->Status(theShape, aRes); |
658 | |
659 | if (aModStatus == 0) |
660 | return anEmptyShape; // No modifications are applied to the shape or its sub-shapes. |
661 | |
662 | return aRes; |
663 | } |
664 | |