0023470: Boolean Fuse between two edges fails
[occt.git] / src / BRepOffsetAPI / BRepOffsetAPI_MiddlePath.cxx
CommitLineData
2277323d 1// File: BRepOffsetAPI_MiddlePath.cxx
2// Created: 06.08.12 16:53:16
3// Author: jgv@ROLEX
4// Copyright: Open CASCADE 2012
5
6#include <BRepOffsetAPI_MiddlePath.ixx>
7#include <BRepOffsetAPI_MiddlePath.hxx>
8
9#include <ShapeUpgrade_UnifySameDomain.hxx>
10
11#include <gp_Lin.hxx>
12#include <Geom_Curve.hxx>
13#include <Geom_TrimmedCurve.hxx>
14#include <Geom_Line.hxx>
15#include <Geom_BezierCurve.hxx>
16#include <Geom_BSplineCurve.hxx>
17#include <BRep_Tool.hxx>
18#include <gce_MakeLin.hxx>
19
20#include <BRepLib_MakeWire.hxx>
21
22#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
23#include <TopExp.hxx>
24#include <TopTools_ListIteratorOfListOfShape.hxx>
25#include <TopoDS.hxx>
26#include <BRepTools.hxx>
27#include <TopTools_SequenceOfShape.hxx>
28#include <BRepTools_WireExplorer.hxx>
29#include <TopoDS_Iterator.hxx>
30#include <BRep_Builder.hxx>
31#include <Precision.hxx>
32#include <TopExp_Explorer.hxx>
33#include <BRepExtrema_DistShapeShape.hxx>
34#include <Geom2d_Curve.hxx>
35#include <Geom2d_Line.hxx>
36#include <GCE2d_MakeLine.hxx>
37#include <BRepLib_MakeEdge.hxx>
38#include <BRepLib.hxx>
39#include <GeomAbs_CurveType.hxx>
40#include <BRepAdaptor_Curve.hxx>
41#include <TopTools_Array1OfShape.hxx>
42#include <BRepLib_MakeFace.hxx>
43#include <TColgp_Array1OfPnt.hxx>
44#include <TColgp_HArray1OfPnt.hxx>
45#include <TColgp_Array1OfVec.hxx>
46#include <TColStd_HArray1OfBoolean.hxx>
47#include <GProp_GProps.hxx>
48#include <BRepGProp.hxx>
49#include <Geom_Circle.hxx>
50#include <gp_Circ.hxx>
51#include <GC_MakeCircle.hxx>
52#include <TColgp_SequenceOfPnt.hxx>
53#include <GeomLib.hxx>
54#include <GeomAPI_Interpolate.hxx>
55
56static Standard_Boolean IsClosed(const TopoDS_Wire& aWire)
57{
58 TopoDS_Vertex V1, V2;
59 TopExp::Vertices(aWire, V1, V2);
60 return (V1.IsSame(V2));
61}
62
63static Standard_Boolean IsLinear(const TopoDS_Edge& anEdge,
64 gp_Lin& aLine)
65{
66 Standard_Real fpar, lpar;
67 Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, fpar, lpar);
68 if (aCurve->IsInstance(STANDARD_TYPE(Geom_TrimmedCurve)))
69 aCurve = ((Handle(Geom_TrimmedCurve)&) aCurve)->BasisCurve();
70
71 gp_Pnt Pnt1, Pnt2;
72 if (aCurve->IsKind(STANDARD_TYPE(Geom_Line)))
73 {
74 aLine = ((Handle(Geom_Line)&) aCurve)->Lin();
75 return Standard_True;
76 }
77 else if (aCurve->IsKind(STANDARD_TYPE(Geom_BezierCurve)))
78 {
79 Handle(Geom_BezierCurve) theBezier = (Handle(Geom_BezierCurve)&) aCurve;
80 if (theBezier->NbPoles() == 2)
81 {
82 Pnt1 = theBezier->Pole(1);
83 Pnt2 = theBezier->Pole(2);
84 aLine = gce_MakeLin(Pnt1, Pnt2);
85 return Standard_True;
86 }
87 }
88 else if (aCurve->IsKind(STANDARD_TYPE(Geom_BSplineCurve)))
89 {
90 Handle(Geom_BSplineCurve) theBSpline = (Handle(Geom_BSplineCurve)&) aCurve;
91 if (theBSpline->NbPoles() == 2)
92 {
93 Pnt1 = theBSpline->Pole(1);
94 Pnt2 = theBSpline->Pole(2);
95 aLine = gce_MakeLin(Pnt1, Pnt2);
96 return Standard_True;
97 }
98 }
99
100 return Standard_False;
101}
102
103static GeomAbs_CurveType TypeOfEdge(const TopoDS_Edge& anEdge)
104{
105 gp_Lin aLin;
106 if (IsLinear(anEdge, aLin))
107 return GeomAbs_Line;
108
109 BRepAdaptor_Curve BAcurve(anEdge);
110 return BAcurve.GetType();
111}
112
113static gp_Vec TangentOfEdge(const TopoDS_Shape& aShape,
114 const Standard_Boolean OnFirst)
115{
116 TopoDS_Edge anEdge = TopoDS::Edge(aShape);
117 TopAbs_Orientation anOr = anEdge.Orientation();
118
119 Standard_Real fpar, lpar;
120 Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, fpar, lpar);
121 Standard_Real thePar;
122 if (OnFirst)
123 thePar = (anOr == TopAbs_FORWARD)? fpar : lpar;
124 else
125 thePar = (anOr == TopAbs_FORWARD)? lpar : fpar;
126
127 gp_Pnt thePoint;
128 gp_Vec theTangent;
129 aCurve->D1(thePar, thePoint, theTangent);
130 if (anOr == TopAbs_REVERSED)
131 theTangent.Reverse();
132
133 return theTangent;
134}
135
136
137static Standard_Boolean IsValidEdge(const TopoDS_Edge& theEdge,
138 const TopoDS_Face& theFace)
139{
140 TopoDS_Vertex V1, V2;
141 TopExp::Vertices(theEdge, V1, V2);
142
143 Standard_Real Tol = Precision::Confusion();
144 Standard_Integer i;
145
146 TopExp_Explorer Explo(theFace, TopAbs_EDGE);
147 for (; Explo.More(); Explo.Next())
148 {
149 const TopoDS_Shape& anEdge = Explo.Current();
150 BRepExtrema_DistShapeShape DistMini(theEdge, anEdge);
151 if (DistMini.Value() <= Tol)
152 {
153 for (i = 1; i <= DistMini.NbSolution(); i++)
154 {
155 BRepExtrema_SupportType theType = DistMini.SupportTypeShape2(i);
156 if (theType == BRepExtrema_IsOnEdge)
157 return Standard_False;
158 //theType is "IsVertex"
159 TopoDS_Shape aVertex = DistMini.SupportOnShape2(i);
160 if (!(aVertex.IsSame(V1) || aVertex.IsSame(V2)))
161 return Standard_False;
162 }
163 }
164 }
165
166 return Standard_True;
167}
168
169/*
170//=======================================================================
171//function : BRepOffsetAPI_MiddlePath
172//purpose : Constructor
173//=======================================================================
174
175BRepOffsetAPI_MiddlePath::BRepOffsetAPI_MiddlePath(const TopoDS_Shape& aShape,
176 const TopoDS_Wire& StartWire)
177{
178 myInitialShape = aShape;
179 myStartWire = StartWire;
180 myClosedSection = myStartWire.Closed();
181}
182
183//=======================================================================
184//function : BRepOffsetAPI_MiddlePath
185//purpose : Constructor
186//=======================================================================
187
188BRepOffsetAPI_MiddlePath::BRepOffsetAPI_MiddlePath(const TopoDS_Shape& aShape,
189 const TopoDS_Edge& StartEdge)
190{
191 myInitialShape = aShape;
192
193 BRepLib_MakeWire MW(StartEdge);
194
195 //BB.Add(myStartWire, StartEdge);
196
197 TopTools_IndexedDataMapOfShapeListOfShape EFmap;
198 TopTools_IndexedDataMapOfShapeListOfShape VEmap;
199 TopExp::MapShapesAndAncestors(myInitialShape, TopAbs_EDGE, TopAbs_FACE, EFmap);
200 TopExp::MapShapesAndAncestors(myInitialShape, TopAbs_VERTEX, TopAbs_EDGE, VEmap);
201
202 //Standard_Boolean Start = Standard_True;
203 //if (Start)
204 //{
205 //TopExp::Vertices(CurEdge, V1, V2);
206 // StartVertex = V1;
207 // CurVertex = V2;
208 // if (VEmap(CurVertex).Extent() == 2) //end: two free edges
209 // {
210 // StartVertex = V2;
211 // CurVertex = V1;
212 // if (VEmap(CurVertex).Extent() == 2) //end: two free edges
213 // break;
214 // }
215 // Start = Standard_False;
216 // continue;
217 //}
218
219 TopoDS_Vertex StartVertex, CurVertex, V1, V2;
220 TopExp::Vertices(StartEdge, StartVertex, CurVertex);
221 TopoDS_Edge CurEdge = StartEdge;
222 Standard_Integer i;
223 for (i = 1; i <= 2; i++)
224 {
225 for (;;)
226 {
227 const TopTools_ListOfShape& LE = VEmap.FindFromKey(CurVertex);
228 if (LE.Extent() == 2) //end: two free edges or one closed free edge
229 break;
230 TopTools_ListIteratorOfListOfShape itl(LE);
231 TopoDS_Edge anEdge;
232 for (; itl.More(); itl.Next())
233 {
234 anEdge = TopoDS::Edge(itl.Value());
235 if (anEdge.IsSame(CurEdge))
236 continue;
237 if (EFmap.FindFromKey(anEdge).Extent() == 1) //another free edge found
238 break;
239 }
240 //BB.Add(myStartWire, anEdge);
241 MW.Add(anEdge);
242 TopExp::Vertices(anEdge, V1, V2);
243 CurVertex = (V1.IsSame(CurVertex))? V2 : V1;
244 CurEdge = anEdge;
245 if (CurVertex.IsSame(StartVertex))
246 break;
247 }
248 if (CurVertex.IsSame(StartVertex))
249 break;
250 CurVertex = StartVertex;
251 CurEdge = StartEdge;
252 }
253
254 myStartWire = MW.Wire();
255 myClosedSection = myStartWire.Closed();
256}
257*/
258
259//=======================================================================
260//function : BRepOffsetAPI_MiddlePath
261//purpose : Constructor
262//=======================================================================
263
264BRepOffsetAPI_MiddlePath::BRepOffsetAPI_MiddlePath(const TopoDS_Shape& aShape,
265 const TopoDS_Shape& StartShape,
266 const TopoDS_Shape& EndShape)
267{
268 ShapeUpgrade_UnifySameDomain Unifier(aShape);
269 Unifier.Build();
270 myInitialShape = Unifier.Shape();
271
272 TopoDS_Wire aStartWire, anEndWire;
273 if (StartShape.ShapeType() == TopAbs_FACE)
274 {
275 const TopoDS_Face& StartFace = TopoDS::Face(StartShape);
276 aStartWire = BRepTools::OuterWire(StartFace);
277 }
278 else
279 aStartWire = TopoDS::Wire(StartShape);
280
281 if (EndShape.ShapeType() == TopAbs_FACE)
282 {
283 const TopoDS_Face& EndFace = TopoDS::Face(EndShape);
284 anEndWire = BRepTools::OuterWire(EndFace);
285 }
286 else
287 anEndWire = TopoDS::Wire(EndShape);
288
289 BRepLib_MakeWire MWstart;
290 //TopTools_MapOfShape MapEdges;
291 BRepTools_WireExplorer wexp(aStartWire);
292 for (; wexp.More(); wexp.Next())
293 {
294 TopoDS_Shape anEdge = wexp.Current();
295 TopoDS_Shape NewEdge = Unifier.Generated(anEdge);
296 if (!NewEdge.IsNull())
297 MWstart.Add(TopoDS::Edge(NewEdge));
298 }
299 myStartWire = MWstart.Wire();
300
301 BRepLib_MakeWire MWend;
302 //MapEdges.Clear();
303 for (wexp.Init(anEndWire); wexp.More(); wexp.Next())
304 {
305 TopoDS_Shape anEdge = wexp.Current();
306 TopoDS_Shape NewEdge = Unifier.Generated(anEdge);
307 if (!NewEdge.IsNull())
308 MWend.Add(TopoDS::Edge(NewEdge));
309 }
310 myEndWire = MWend.Wire();
311
312 myClosedSection = myStartWire.Closed();
313 myClosedRing = myStartWire.IsSame(myEndWire);
314}
315
316//=======================================================================
317//function : Build
318//purpose :
319//=======================================================================
320
321void BRepOffsetAPI_MiddlePath::Build()
322{
323 TopTools_ListIteratorOfListOfShape itl;
324
325 TopTools_SequenceOfShape StartVertices;
326 TopTools_MapOfShape EndVertices;
327 TopTools_MapOfShape EndEdges;
328 BRepOffsetAPI_SequenceOfSequenceOfShape SectionsEdges;
329
330 BRepTools_WireExplorer wexp(myStartWire);
331 TopTools_SequenceOfShape EdgeSeq;
332 for (; wexp.More(); wexp.Next())
333 {
334 StartVertices.Append(wexp.CurrentVertex());
335 EdgeSeq.Append(wexp.Current());
336 }
337 if (!myClosedSection)
338 StartVertices.Append(wexp.CurrentVertex());
339 SectionsEdges.Append(EdgeSeq);
340
341 for (wexp.Init(myEndWire); wexp.More(); wexp.Next())
342 {
343 EndVertices.Add(wexp.CurrentVertex());
344 EndEdges.Add(wexp.Current());
345 }
346 if (!myClosedSection)
347 EndVertices.Add(wexp.CurrentVertex());
348
349
350 TopoDS_Iterator itw(myStartWire);
351 for (; itw.More(); itw.Next())
352 myStartWireEdges.Add(itw.Value());
353 for (itw.Initialize(myEndWire); itw.More(); itw.Next())
354 myEndWireEdges.Add(itw.Value());
355
356 TopTools_IndexedDataMapOfShapeListOfShape VEmap;
357 TopTools_IndexedDataMapOfShapeListOfShape EFmap;
358 TopExp::MapShapesAndAncestors(myInitialShape, TopAbs_VERTEX, TopAbs_EDGE, VEmap);
359 TopExp::MapShapesAndAncestors(myInitialShape, TopAbs_EDGE, TopAbs_FACE, EFmap);
360
361 TopTools_MapOfShape CurVertices;
362
363 Standard_Integer i, j, k;
364 TopoDS_Edge anEdge, theEdge;
365 TopoDS_Vertex V1, V2, NextVertex;
366 //Initialization of <myPaths>
367 for (i = 1; i <= StartVertices.Length(); i++)
368 {
369 TopTools_SequenceOfShape Edges;
370 const TopTools_ListOfShape& LE = VEmap.FindFromKey(StartVertices(i));
371 for (itl.Initialize(LE); itl.More(); itl.Next())
372 {
373 anEdge = TopoDS::Edge(itl.Value());
374 if (!myStartWireEdges.Contains(anEdge))
375 {
376 TopExp::Vertices(anEdge, V1, V2, Standard_True);
377 if (V1.IsSame(StartVertices(i)))
378 CurVertices.Add(V2);
379 else
380 {
381 anEdge.Reverse();
382 CurVertices.Add(V1);
383 }
384 Edges.Append(anEdge);
385 break;
386 }
387 }
388 myPaths.Append(Edges);
389 }
390
391 //Filling of "myPaths"
392 //TopTools_MapOfShape StartFacesMap;
393 TopTools_ListOfShape NextVertices;
394 for (;;)
395 {
396 /*
397 StartFacesMap.Clear();
398 for (i = 1; i <= myPaths.Length(); i++)
399 {
400 const TopoDS_Shape& LastEdge = myPaths(i).Last();
401 const TopTools_ListOfShape& LF = EFmap(LastEdge);
402 for (itl.Initialize(LF); itl.More(); itl.Next())
403 StartFacesMap.Add(itl.Value();
404 }
405 */
406 //TopTools_SequenceOfShape NewEdges;
407 for (i = 1; i <= myPaths.Length(); i++)
408 {
409 theEdge = TopoDS::Edge(myPaths(i).Last());
410 TopoDS_Vertex theVertex = TopExp::LastVertex(theEdge, Standard_True);
411 if (EndVertices.Contains(theVertex))
412 continue;
413 const TopTools_ListOfShape& LE = VEmap.FindFromKey(theVertex);
414 Standard_Boolean NextEdgeFound = Standard_False;
415 for (itl.Initialize(LE); itl.More(); itl.Next())
416 {
417 anEdge = TopoDS::Edge(itl.Value());
418 if (anEdge.IsSame(theEdge))
419 continue;
420 TopExp::Vertices(anEdge, V1, V2, Standard_True);
421 if (V1.IsSame(theVertex))
422 NextVertex = V2;
423 else
424 {
425 anEdge.Reverse();
426 NextVertex = V1;
427 }
428 if (!CurVertices.Contains(NextVertex))
429 {
430 NextEdgeFound = Standard_True;
431 break;
432 }
433 }
434 if (NextEdgeFound)
435 {
436 myPaths(i).Append(anEdge);
437 NextVertices.Append(NextVertex);
438 }
439 }
440 if (NextVertices.IsEmpty())
441 break;
442 for (itl.Initialize(NextVertices); itl.More(); itl.Next())
443 CurVertices.Add(itl.Value());
444 NextVertices.Clear();
445 }
446
447 //Building of set of sections
448 Standard_Integer NbE = EdgeSeq.Length();
449 Standard_Integer NbVer = myPaths.Length();
450 if (myClosedSection)
451 NbVer++;
452 i = 1;
453 for (;;)
454 {
455 for (j = 1; j <= EdgeSeq.Length(); j++)
456 EdgeSeq(j).Nullify();
457
458 Standard_Boolean ToInsertVertex = Standard_False;
459
460 for (j = 2; j <= NbVer; j++)
461 {
462 if (!EdgeSeq(j-1).IsNull())
463 continue;
464
465 if (ToInsertVertex)
466 {
467 if (myPaths(j-1)(i).ShapeType() == TopAbs_EDGE)
468 {
469 TopoDS_Edge aE1 = TopoDS::Edge(myPaths(j-1)(i));
470 TopoDS_Shape fver = TopExp::FirstVertex(aE1, Standard_True);
471 myPaths(j-1).InsertBefore(i, fver);
472 }
473 if (myPaths((j<=NbE)? j : 1)(i).ShapeType() == TopAbs_EDGE)
474 {
475 TopoDS_Edge aE2 = TopoDS::Edge(myPaths((j<=NbE)? j : 1)(i));
476 TopoDS_Shape fver = TopExp::FirstVertex(aE2, Standard_True);
477 myPaths((j<=NbE)? j : 1).InsertBefore(i, fver);
478 }
479 ToInsertVertex = Standard_False;
480 }
481
482 TopoDS_Edge E1, E2;
483 if (myPaths(j-1)(i).ShapeType() == TopAbs_EDGE)
484 E1 = TopoDS::Edge(myPaths(j-1)(i));
485 if (myPaths((j<=NbE)? j : 1)(i).ShapeType() == TopAbs_EDGE)
486 E2 = TopoDS::Edge(myPaths((j<=NbE)? j : 1)(i));
487 TopoDS_Edge E12 = TopoDS::Edge(SectionsEdges(i)(j-1));
488
489 //TopoDS_Vertex PrevVertex = TopoDS::Vertex(VerSeq(j-1));
490 //TopoDS_Vertex CurVertex = TopoDS::Vertex(VerSeq(j));
491 TopoDS_Vertex PrevVertex = (E1.IsNull())? TopoDS::Vertex(myPaths(j-1)(i))
492 : TopExp::LastVertex(E1, Standard_True);
493 TopoDS_Vertex CurVertex = (E2.IsNull())? TopoDS::Vertex(myPaths((j<=NbE)? j : 1)(i))
494 : TopExp::LastVertex(E2, Standard_True);
495
496 TopoDS_Edge ProperEdge;
497 const TopTools_ListOfShape& LE = VEmap.FindFromKey(PrevVertex);
498 //Temporary
499 Standard_Integer LenList = LE.Extent();
500 ///////////
501 for (itl.Initialize(LE); itl.More(); itl.Next())
502 {
503 anEdge = TopoDS::Edge(itl.Value());
504 TopExp::Vertices(anEdge, V1, V2);
505 if ((V1.IsSame(PrevVertex) && V2.IsSame(CurVertex) ||
506 V1.IsSame(CurVertex) && V2.IsSame(PrevVertex)) &&
507 !anEdge.IsSame(E1))
508 {
509 ProperEdge = anEdge;
510 break;
511 }
512 }
513
514 if ((myPaths(j-1)(i)).ShapeType() == TopAbs_VERTEX &&
515 (myPaths((j<=NbE)? j : 1)(i)).ShapeType() == TopAbs_VERTEX)
516 {
517 EdgeSeq(j-1) = ProperEdge;
518 continue;
519 }
520
521 TopoDS_Vertex PrevPrevVer = (E1.IsNull())? PrevVertex
522 : TopExp::FirstVertex(E1, Standard_True);
523 TopoDS_Vertex PrevCurVer = (E2.IsNull())? CurVertex
524 : TopExp::FirstVertex(E2, Standard_True);
525 if (ProperEdge.IsNull()) //no connection between these two vertices
526 {
527 //ToInsertVertex = Standard_False;
528 const TopoDS_Shape& EE1 = (E1.IsNull())?
529 myPaths(j-1)(i-1) : E1;
530 const TopoDS_Shape& EE2 = (E2.IsNull())?
531 myPaths((j<=NbE)? j : 1)(i-1) : E2;
532 const TopTools_ListOfShape& LF = EFmap.FindFromKey(EE1);
533 TopoDS_Face theFace;
534 for (itl.Initialize(LF); itl.More(); itl.Next())
535 {
536 const TopoDS_Shape& aFace = itl.Value();
537 TopExp_Explorer Explo(aFace, TopAbs_EDGE);
538 for (; Explo.More(); Explo.Next())
539 {
540 if (EE2.IsSame(Explo.Current()))
541 {
542 const TopTools_ListOfShape& LFsec = EFmap.FindFromKey(E12);
543 TopTools_ListIteratorOfListOfShape itlsec(LFsec);
544 for (; itlsec.More(); itlsec.Next())
545 if (aFace.IsSame(itlsec.Value()))
546 {
547 theFace = TopoDS::Face(aFace);
548 break;
549 }
550 if (!theFace.IsNull())
551 break;
552 }
553 }
554 if (!theFace.IsNull())
555 break;
556 }
557 TopTools_ListOfShape ListOneFace;
558 ListOneFace.Append(theFace);
559
560 if (E1.IsNull() || E2.IsNull())
561 {
562 if (E1.IsNull())
563 E1 = TopoDS::Edge(myPaths(j-1)(i-1));
564 if (E2.IsNull())
565 E2 = TopoDS::Edge(myPaths((j<=NbE)? j : 1)(i-1));
566 Standard_Real fpar1, lpar1, fpar2, lpar2;
567 Standard_Real FirstPar1, LastPar1, FirstPar2, LastPar2;
568 Handle(Geom2d_Curve) PCurve1 = BRep_Tool::CurveOnSurface(E1, theFace, fpar1, lpar1);
569 Handle(Geom2d_Curve) PCurve2 = BRep_Tool::CurveOnSurface(E2, theFace, fpar2, lpar2);
570 if (E1.Orientation() == TopAbs_FORWARD)
571 { FirstPar1 = fpar1; LastPar1 = lpar1; }
572 else
573 { FirstPar1 = lpar1; LastPar1 = fpar1; }
574 if (E2.Orientation() == TopAbs_FORWARD)
575 { FirstPar2 = fpar2; LastPar2 = lpar2; }
576 else
577 { FirstPar2 = lpar2; LastPar2 = fpar2; }
578 gp_Pnt2d FirstPnt2d = PCurve1->Value(LastPar1);
579 gp_Pnt2d LastPnt2d = PCurve2->Value(LastPar2);
580 Handle(Geom_Surface) theSurf = BRep_Tool::Surface(theFace);
581 Handle(Geom2d_Line) theLine = GCE2d_MakeLine(FirstPnt2d, LastPnt2d);
582 Standard_Real len_ne = FirstPnt2d.Distance(LastPnt2d);
583 TopoDS_Edge NewEdge = BRepLib_MakeEdge(theLine, theSurf,
584 PrevVertex, CurVertex,
585 0., len_ne);
586 BRepLib::BuildCurve3d(NewEdge);
587 EdgeSeq(j-1) = NewEdge;
588 EFmap.Add(NewEdge, ListOneFace);
589 }
590 else //E1 is edge
591 {
592 //Extract points 2d
593 Standard_Real fpar1, lpar1, fpar2, lpar2;
594 Standard_Real FirstPar1, LastPar1, FirstPar2, LastPar2;
595 Handle(Geom2d_Curve) PCurve1 = BRep_Tool::CurveOnSurface(E1, theFace, fpar1, lpar1);
596 Handle(Geom2d_Curve) PCurve2 = BRep_Tool::CurveOnSurface(E2, theFace, fpar2, lpar2);
597 if (E1.Orientation() == TopAbs_FORWARD)
598 { FirstPar1 = fpar1; LastPar1 = lpar1; }
599 else
600 { FirstPar1 = lpar1; LastPar1 = fpar1; }
601 if (E2.Orientation() == TopAbs_FORWARD)
602 { FirstPar2 = fpar2; LastPar2 = lpar2; }
603 else
604 { FirstPar2 = lpar2; LastPar2 = fpar2; }
605 gp_Pnt2d FirstPnt2d = PCurve1->Value(LastPar1);
606 gp_Pnt2d LastPnt2d = PCurve2->Value(LastPar2);
607 Handle(Geom_Surface) theSurf = BRep_Tool::Surface(theFace);
608 Handle(Geom2d_Line) theLine = GCE2d_MakeLine(FirstPnt2d, LastPnt2d);
609 Standard_Real len_ne = FirstPnt2d.Distance(LastPnt2d);
610 TopoDS_Edge NewEdge = BRepLib_MakeEdge(theLine, theSurf,
611 PrevVertex, CurVertex,
612 0., len_ne);
613 BRepLib::BuildCurve3d(NewEdge);
614 gp_Pnt2d PrevFirstPnt2d = PCurve1->Value(FirstPar1);
615 gp_Pnt2d PrevLastPnt2d = PCurve2->Value(FirstPar2);
616 Handle(Geom2d_Line) Line1 = GCE2d_MakeLine(PrevFirstPnt2d, LastPnt2d);
617 Handle(Geom2d_Line) Line2 = GCE2d_MakeLine(FirstPnt2d, PrevLastPnt2d);
618 Standard_Real len_ne1 = PrevFirstPnt2d.Distance(LastPnt2d);
619 TopoDS_Edge NewEdge1 = BRepLib_MakeEdge(Line1, theSurf,
620 PrevPrevVer, CurVertex,
621 0., len_ne1);
622 BRepLib::BuildCurve3d(NewEdge1);
623 Standard_Real len_ne2 = FirstPnt2d.Distance(PrevLastPnt2d);
624 TopoDS_Edge NewEdge2 = BRepLib_MakeEdge(Line2, theSurf,
625 PrevVertex, PrevCurVer,
626 0., len_ne2);
627 BRepLib::BuildCurve3d(NewEdge2);
628 Standard_Boolean good_ne = IsValidEdge(NewEdge, theFace);
629 Standard_Boolean good_ne1 = IsValidEdge(NewEdge1, theFace);
630 Standard_Boolean good_ne2 = IsValidEdge(NewEdge2, theFace);
631
632 GeomAbs_CurveType type_E1 = TypeOfEdge(E1);
633 GeomAbs_CurveType type_E2 = TypeOfEdge(E2);
634
635 Standard_Integer ChooseEdge = 0;
636
637 if (!good_ne || type_E1 != type_E2)
638 {
639 if (type_E1 == type_E2) //!good_ne
640 {
641 if (good_ne1)
642 ChooseEdge = 1;
643 else
644 ChooseEdge = 2;
645 }
646 else //types are different
647 {
648 if (type_E1 == GeomAbs_Line)
649 ChooseEdge = 1;
650 else if (type_E2 == GeomAbs_Line)
651 ChooseEdge = 2;
652 else //to be developed later...
653 {}
654 }
655 }
656
657 if (ChooseEdge == 0)
658 {
659 EdgeSeq(j-1) = NewEdge;
660 EFmap.Add(NewEdge, ListOneFace);
661 }
662 else if (ChooseEdge == 1)
663 {
664 EdgeSeq(j-1) = NewEdge1;
665 EFmap.Add(NewEdge1, ListOneFace);
666 for (k = 1; k < j-1; k++)
667 EdgeSeq(k).Nullify();
668 for (k = 1; k <= j-1; k++)
669 {
670 TopoDS_Edge aLastEdge = TopoDS::Edge(myPaths(k)(i));
671 TopoDS_Shape VertexAsEdge = TopExp::FirstVertex(aLastEdge, Standard_True);
672 myPaths(k).InsertBefore(i, VertexAsEdge);
673 }
674 j = 1;
675 }
676 else if (ChooseEdge == 2)
677 {
678 EdgeSeq(j-1) = NewEdge2;
679 EFmap.Add(NewEdge2, ListOneFace);
680 ToInsertVertex = Standard_True;
681 }
682 } //else //E1 is edge
683 } //if (ProperEdge.IsNull())
684 else //connecting edge exists
685 {
686 /*
687 if (ToInsertVertex)
688 {
689 myPaths(j-1).InsertBefore(i, PrevPrevVer);
690 myPaths((j<=NbE)? j : 1).InsertBefore(i, PrevCurVer);
691 EdgeSeq(j-1) = E12;
692 }
693 else
694 */
695 EdgeSeq(j-1) = ProperEdge;
696 }
697 } //for (j = 2; j <= NbVer; j++)
698 SectionsEdges.Append(EdgeSeq);
699
700 //check for exit from for(;;)
701 Standard_Integer NbEndEdges = 0;
702 for (j = 1; j <= EdgeSeq.Length(); j++)
703 if (EndEdges.Contains(EdgeSeq(j)))
704 NbEndEdges++;
705 if (NbEndEdges == NbE)
706 break;
707
708 i++;
709 } //for (;;)
710
711
712 //final phase: building of middle path
713 Standard_Integer NbSecFaces = SectionsEdges.Length();
714 TopTools_Array1OfShape SecFaces(1, NbSecFaces);
715 for (i = 1; i <= NbSecFaces; i++)
716 {
717 BRepLib_MakeWire MW;
718 for (j = 1; j <= NbE; j++)
719 {
720 anEdge = TopoDS::Edge(SectionsEdges(i)(j));
721 MW.Add(anEdge);
722 }
723 if (!myClosedSection)
724 {
725 TopExp::Vertices(MW.Wire(), V1, V2);
726 anEdge = BRepLib_MakeEdge(V2, V1);
727 MW.Add(anEdge);
728 }
729 TopoDS_Wire aWire = MW.Wire();
730 BRepLib_MakeFace MF(aWire, Standard_True); //Only plane
731 if (MF.IsDone())
732 SecFaces(i) = MF.Face();
733 else
734 SecFaces(i) = aWire;
735 }
736
737 TColgp_Array1OfPnt Centers(1, NbSecFaces);
738 for (i = 1; i <= NbSecFaces; i++)
739 {
740 GProp_GProps Properties;
741 if (SecFaces(i).ShapeType() == TopAbs_FACE)
742 BRepGProp::SurfaceProperties(SecFaces(i), Properties);
743 else //wire
744 BRepGProp::LinearProperties(SecFaces(i), Properties);
745
746 Centers(i) = Properties.CentreOfMass();
747 }
748
749 TopTools_Array1OfShape MidEdges(1, NbSecFaces-1);
750 Standard_Real LinTol = 1.e-5;
751 Standard_Real AngTol = 1.e-7;
752 gp_Pnt Pnt1, Pnt2;
753 for (i = 1; i < NbSecFaces; i++)
754 {
755 GeomAbs_CurveType TypeOfMidEdge = GeomAbs_OtherCurve;
756 for (j = 1; j <= myPaths.Length(); j++)
757 {
758 const TopoDS_Shape& aShape = myPaths(j)(i);
759 if (aShape.ShapeType() == TopAbs_VERTEX)
760 {
761 TypeOfMidEdge = GeomAbs_OtherCurve;
762 break;
763 }
764 anEdge = TopoDS::Edge(aShape);
765 GeomAbs_CurveType aType = TypeOfEdge(anEdge);
766 if (j == 1)
767 TypeOfMidEdge = aType;
768 else
769 {
770 if (aType != TypeOfMidEdge)
771 {
772 TypeOfMidEdge = GeomAbs_OtherCurve;
773 break;
774 }
775 }
776 }
777 if (TypeOfMidEdge == GeomAbs_Line)
778 MidEdges(i) = BRepLib_MakeEdge(Centers(i), Centers(i+1));
779 else if (TypeOfMidEdge == GeomAbs_Circle)
780 {
781 gp_Ax1 theAxis;
782 gp_Dir theDir1, theDir2;
783 Standard_Real theAngle;
784 Standard_Boolean SimilarArcs = Standard_True;
785 for (j = 1; j <= myPaths.Length(); j++)
786 {
787 anEdge = TopoDS::Edge(myPaths(j)(i));
788 Standard_Real fpar, lpar;
789 Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, fpar, lpar);
790 if (aCurve->IsInstance(STANDARD_TYPE(Geom_TrimmedCurve)))
791 aCurve = ((Handle(Geom_TrimmedCurve)&) aCurve)->BasisCurve();
792 Pnt1 = aCurve->Value(fpar);
793 Pnt2 = aCurve->Value(lpar);
794 Handle(Geom_Circle) aCircle = Handle(Geom_Circle)::DownCast(aCurve);
795 gp_Circ aCirc = aCircle->Circ();
796 if (j == 1)
797 {
798 theAxis = aCirc.Axis();
799 theDir1 = gp_Vec(aCirc.Location(), Pnt1);
800 theDir2 = gp_Vec(aCirc.Location(), Pnt2);
801 theAngle = lpar - fpar;
802 }
803 else
804 {
805 gp_Ax1 anAxis = aCirc.Axis();
806 gp_Lin aLin(anAxis);
807 if (!aLin.Contains(theAxis.Location(), LinTol) ||
808 !anAxis.IsParallel(theAxis, AngTol))
809 {
810 SimilarArcs = Standard_False;
811 break;
812 }
813 gp_Dir aDir1 = gp_Vec(aCirc.Location(), Pnt1);
814 gp_Dir aDir2 = gp_Vec(aCirc.Location(), Pnt2);
815 if (!(aDir1.IsEqual(theDir1, AngTol) && aDir2.IsEqual(theDir2, AngTol) ||
816 aDir1.IsEqual(theDir2, AngTol) && aDir2.IsEqual(theDir1, AngTol)))
817 {
818 SimilarArcs = Standard_False;
819 break;
820 }
821 }
822 }
823 if (SimilarArcs)
824 {
825 gp_XYZ AxisLoc = theAxis.Location().XYZ();
826 gp_XYZ AxisDir = theAxis.Direction().XYZ();
827 Standard_Real Parameter = (Centers(i).XYZ() - AxisLoc) * AxisDir;
828 gp_Pnt theCenterOfCirc(AxisLoc + Parameter*AxisDir);
829
830 gp_Vec Vec1(theCenterOfCirc, Centers(i));
831 gp_Vec Vec2(theCenterOfCirc, Centers(i+1));
832 /*
833 gp_Dir VecProd = Vec1 ^ Vec2;
834 if (theAxis.Direction() * VecProd < 0.)
835 theAxis.Reverse();
836 */
837
838 Standard_Real anAngle = Vec1.AngleWithRef(Vec2, theAxis.Direction());
839 if (anAngle < 0.)
840 anAngle += 2.*M_PI;
841 if (Abs(anAngle - theAngle) > AngTol)
842 theAxis.Reverse();
843 gp_Ax2 theAx2(theCenterOfCirc, theAxis.Direction(), Vec1);
844 Handle(Geom_Circle) theCircle = GC_MakeCircle(theAx2, Vec1.Magnitude());
845 MidEdges(i) = BRepLib_MakeEdge(theCircle, 0., theAngle);
846 }
847 }
848 }
849
850 //Build missed edges
851 for (i = 1; i < NbSecFaces; i++)
852 {
853 if (MidEdges(i).IsNull())
854 {
855 for (j = i+1; j < NbSecFaces; j++)
856 {
857 if (!MidEdges(j).IsNull())
858 break;
859 }
860 //from i to j-1 all edges are null
861 Handle(TColgp_HArray1OfPnt) thePoints = new TColgp_HArray1OfPnt(1, j-i+1);
862 TColgp_Array1OfVec theTangents(1, j-i+1);
863 Handle(TColStd_HArray1OfBoolean) theFlags = new TColStd_HArray1OfBoolean(1, j-i+1);
864 for (k = i; k <= j; k++)
865 thePoints->SetValue(k-i+1, Centers(k));
866 for (k = i; k <= j; k++)
867 {
868 TColgp_SequenceOfPnt PntSeq;
869 for (Standard_Integer indp = 1; indp <= myPaths.Length(); indp++)
870 {
871 gp_Vec aTangent;
872 if (k == i)
873 {
874 if (myPaths(indp)(k).ShapeType() == TopAbs_VERTEX)
875 continue;
876 aTangent = TangentOfEdge(myPaths(indp)(k), Standard_True); //at begin
877 }
878 else if (k == j)
879 {
880 if (myPaths(indp)(k-1).ShapeType() == TopAbs_VERTEX)
881 continue;
882 aTangent = TangentOfEdge(myPaths(indp)(k-1), Standard_False); //at end
883 }
884 else
885 {
886 if (myPaths(indp)(k-1).ShapeType() == TopAbs_VERTEX ||
887 myPaths(indp)(k).ShapeType() == TopAbs_VERTEX)
888 continue;
889 gp_Vec Tangent1 = TangentOfEdge(myPaths(indp)(k-1), Standard_False); //at end
890 gp_Vec Tangent2 = TangentOfEdge(myPaths(indp)(k), Standard_True); //at begin
891 aTangent = Tangent1 + Tangent2;
892 }
893 aTangent.Normalize();
894 gp_Pnt aPnt(aTangent.XYZ());
895 PntSeq.Append(aPnt);
896 }
897 TColgp_Array1OfPnt PntArray(1, PntSeq.Length());
898 for (Standard_Integer ip = 1; ip <= PntSeq.Length(); ip++)
899 PntArray(ip) = PntSeq(ip);
900 gp_Pnt theBary;
901 gp_Dir xdir, ydir;
902 Standard_Real xgap, ygap, zgap;
903 GeomLib::Inertia(PntArray, theBary, xdir, ydir, xgap, ygap, zgap);
904 gp_Vec theTangent(theBary.XYZ());
905 theTangents(k-i+1) = theTangent;
906 }
907 theFlags->Init(Standard_True);
908
909 GeomAPI_Interpolate Interpol(thePoints, Standard_False, LinTol);
910 Interpol.Load(theTangents, theFlags);
911 Interpol.Perform();
912 if (!Interpol.IsDone())
913 {
914 cout<<endl<<"Interpolation failed"<<endl;
915 }
916 Handle(Geom_Curve) InterCurve = Interpol.Curve();
917 MidEdges(i) = BRepLib_MakeEdge(InterCurve);
918 i = j;
919 }
920 }
921
922 BRepLib_MakeWire MakeFinalWire;
923 for (i = 1; i < NbSecFaces; i++)
924 if (!MidEdges(i).IsNull())
925 MakeFinalWire.Add(TopoDS::Edge(MidEdges(i)));
926
927 TopoDS_Wire FinalWire = MakeFinalWire.Wire();
928 myShape = MakeFinalWire.Wire();
929
930 //Temporary
931 /*
932 TopoDS_Compound aCompound, aCmp1, aCmp2;
933 BRep_Builder BB;
934 BB.MakeCompound(aCompound);
935 BB.MakeCompound(aCmp1);
936 BB.MakeCompound(aCmp2);
937 for (i = 1; i <= myPaths.Length(); i++)
938 {
939 TopoDS_Compound aCmp;
940 BB.MakeCompound(aCmp);
941 for (j = 1; j <= myPaths(i).Length(); j++)
942 BB.Add(aCmp, myPaths(i)(j));
943 BB.Add(aCmp1, aCmp);
944 }
945 for (i = 1; i <= SectionsEdges.Length(); i++)
946 {
947 TopoDS_Wire aWire;
948 BB.MakeWire(aWire);
949 for (j = 1; j <= SectionsEdges(i).Length(); j++)
950 BB.Add(aWire, SectionsEdges(i)(j));
951 BB.Add(aCmp2, aWire);
952 }
953 BB.Add(aCompound, aCmp1);
954 BB.Add(aCompound, aCmp2);
955 BB.Add(aCompound, FinalWire);
956
957 myShape = aCompound;
958 */
959 ////////////
960
961 Done();
962}