1 // Created on: 2012-08-06
2 // Created by: jgv@ROLEX
3 // Copyright (c) 2012-2014 OPEN CASCADE SAS
5 // This file is part of Open CASCADE Technology software library.
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
16 #include <BRepOffsetAPI_MiddlePath.ixx>
17 #include <BRepOffsetAPI_MiddlePath.hxx>
19 #include <ShapeUpgrade_UnifySameDomain.hxx>
22 #include <Geom_Curve.hxx>
23 #include <Geom_TrimmedCurve.hxx>
24 #include <Geom_Line.hxx>
25 #include <Geom_BezierCurve.hxx>
26 #include <Geom_BSplineCurve.hxx>
27 #include <BRep_Tool.hxx>
28 #include <gce_MakeLin.hxx>
30 #include <BRepLib_MakeWire.hxx>
32 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
33 #include <TopTools_MapIteratorOfMapOfShape.hxx>
35 #include <TopTools_ListIteratorOfListOfShape.hxx>
37 #include <BRepTools.hxx>
38 #include <TopTools_SequenceOfShape.hxx>
39 #include <BRepTools_WireExplorer.hxx>
40 #include <TopoDS_Iterator.hxx>
41 #include <BRep_Builder.hxx>
42 #include <Precision.hxx>
43 #include <TopExp_Explorer.hxx>
44 #include <BRepExtrema_DistShapeShape.hxx>
45 #include <Geom2d_Curve.hxx>
46 #include <Geom2d_Line.hxx>
47 #include <GCE2d_MakeLine.hxx>
48 #include <BRepLib_MakeEdge.hxx>
49 #include <BRepLib.hxx>
50 #include <GeomAbs_CurveType.hxx>
51 #include <BRepAdaptor_Curve.hxx>
52 #include <TopTools_Array1OfShape.hxx>
53 #include <BRepLib_MakeFace.hxx>
54 #include <TColgp_Array1OfPnt.hxx>
55 #include <TColgp_HArray1OfPnt.hxx>
56 #include <TColgp_Array1OfVec.hxx>
57 #include <TColStd_HArray1OfBoolean.hxx>
58 #include <GProp_GProps.hxx>
59 #include <BRepGProp.hxx>
60 #include <Geom_Circle.hxx>
61 #include <gp_Circ.hxx>
62 #include <GC_MakeCircle.hxx>
63 #include <TColgp_SequenceOfPnt.hxx>
64 #include <GeomLib.hxx>
65 #include <GeomAPI_Interpolate.hxx>
67 static Standard_Boolean IsLinear(const TopoDS_Edge& anEdge,
70 Standard_Real fpar, lpar;
71 Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, fpar, lpar);
72 if (aCurve->IsInstance(STANDARD_TYPE(Geom_TrimmedCurve)))
73 aCurve = ((Handle(Geom_TrimmedCurve)&) aCurve)->BasisCurve();
76 if (aCurve->IsKind(STANDARD_TYPE(Geom_Line)))
78 aLine = ((Handle(Geom_Line)&) aCurve)->Lin();
81 else if (aCurve->IsKind(STANDARD_TYPE(Geom_BezierCurve)))
83 Handle(Geom_BezierCurve) theBezier = (Handle(Geom_BezierCurve)&) aCurve;
84 if (theBezier->NbPoles() == 2)
86 Pnt1 = theBezier->Pole(1);
87 Pnt2 = theBezier->Pole(2);
88 aLine = gce_MakeLin(Pnt1, Pnt2);
92 else if (aCurve->IsKind(STANDARD_TYPE(Geom_BSplineCurve)))
94 Handle(Geom_BSplineCurve) theBSpline = (Handle(Geom_BSplineCurve)&) aCurve;
95 if (theBSpline->NbPoles() == 2)
97 Pnt1 = theBSpline->Pole(1);
98 Pnt2 = theBSpline->Pole(2);
99 aLine = gce_MakeLin(Pnt1, Pnt2);
100 return Standard_True;
104 return Standard_False;
107 static GeomAbs_CurveType TypeOfEdge(const TopoDS_Edge& anEdge)
110 if (IsLinear(anEdge, aLin))
113 BRepAdaptor_Curve BAcurve(anEdge);
114 return BAcurve.GetType();
117 static gp_Vec TangentOfEdge(const TopoDS_Shape& aShape,
118 const Standard_Boolean OnFirst)
120 TopoDS_Edge anEdge = TopoDS::Edge(aShape);
121 TopAbs_Orientation anOr = anEdge.Orientation();
123 Standard_Real fpar, lpar;
124 Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, fpar, lpar);
125 Standard_Real thePar;
127 thePar = (anOr == TopAbs_FORWARD)? fpar : lpar;
129 thePar = (anOr == TopAbs_FORWARD)? lpar : fpar;
133 aCurve->D1(thePar, thePoint, theTangent);
134 if (anOr == TopAbs_REVERSED)
135 theTangent.Reverse();
141 static Standard_Boolean IsValidEdge(const TopoDS_Edge& theEdge,
142 const TopoDS_Face& theFace)
144 TopoDS_Vertex V1, V2;
145 TopExp::Vertices(theEdge, V1, V2);
147 Standard_Real Tol = Precision::Confusion();
150 TopExp_Explorer Explo(theFace, TopAbs_EDGE);
151 for (; Explo.More(); Explo.Next())
153 const TopoDS_Shape& anEdge = Explo.Current();
154 BRepExtrema_DistShapeShape DistMini(theEdge, anEdge);
155 if (DistMini.Value() <= Tol)
157 for (i = 1; i <= DistMini.NbSolution(); i++)
159 BRepExtrema_SupportType theType = DistMini.SupportTypeShape2(i);
160 if (theType == BRepExtrema_IsOnEdge)
161 return Standard_False;
162 //theType is "IsVertex"
163 TopoDS_Shape aVertex = DistMini.SupportOnShape2(i);
164 if (!(aVertex.IsSame(V1) || aVertex.IsSame(V2)))
165 return Standard_False;
170 return Standard_True;
174 //=======================================================================
175 //function : BRepOffsetAPI_MiddlePath
176 //purpose : Constructor
177 //=======================================================================
179 BRepOffsetAPI_MiddlePath::BRepOffsetAPI_MiddlePath(const TopoDS_Shape& aShape,
180 const TopoDS_Wire& StartWire)
182 myInitialShape = aShape;
183 myStartWire = StartWire;
184 myClosedSection = myStartWire.Closed();
187 //=======================================================================
188 //function : BRepOffsetAPI_MiddlePath
189 //purpose : Constructor
190 //=======================================================================
192 BRepOffsetAPI_MiddlePath::BRepOffsetAPI_MiddlePath(const TopoDS_Shape& aShape,
193 const TopoDS_Edge& StartEdge)
195 myInitialShape = aShape;
197 BRepLib_MakeWire MW(StartEdge);
199 //BB.Add(myStartWire, StartEdge);
201 TopTools_IndexedDataMapOfShapeListOfShape EFmap;
202 TopTools_IndexedDataMapOfShapeListOfShape VEmap;
203 TopExp::MapShapesAndAncestors(myInitialShape, TopAbs_EDGE, TopAbs_FACE, EFmap);
204 TopExp::MapShapesAndAncestors(myInitialShape, TopAbs_VERTEX, TopAbs_EDGE, VEmap);
206 //Standard_Boolean Start = Standard_True;
209 //TopExp::Vertices(CurEdge, V1, V2);
212 // if (VEmap(CurVertex).Extent() == 2) //end: two free edges
216 // if (VEmap(CurVertex).Extent() == 2) //end: two free edges
219 // Start = Standard_False;
223 TopoDS_Vertex StartVertex, CurVertex, V1, V2;
224 TopExp::Vertices(StartEdge, StartVertex, CurVertex);
225 TopoDS_Edge CurEdge = StartEdge;
227 for (i = 1; i <= 2; i++)
231 const TopTools_ListOfShape& LE = VEmap.FindFromKey(CurVertex);
232 if (LE.Extent() == 2) //end: two free edges or one closed free edge
234 TopTools_ListIteratorOfListOfShape itl(LE);
236 for (; itl.More(); itl.Next())
238 anEdge = TopoDS::Edge(itl.Value());
239 if (anEdge.IsSame(CurEdge))
241 if (EFmap.FindFromKey(anEdge).Extent() == 1) //another free edge found
244 //BB.Add(myStartWire, anEdge);
246 TopExp::Vertices(anEdge, V1, V2);
247 CurVertex = (V1.IsSame(CurVertex))? V2 : V1;
249 if (CurVertex.IsSame(StartVertex))
252 if (CurVertex.IsSame(StartVertex))
254 CurVertex = StartVertex;
258 myStartWire = MW.Wire();
259 myClosedSection = myStartWire.Closed();
263 //=======================================================================
264 //function : BRepOffsetAPI_MiddlePath
265 //purpose : Constructor
266 //=======================================================================
268 BRepOffsetAPI_MiddlePath::BRepOffsetAPI_MiddlePath(const TopoDS_Shape& aShape,
269 const TopoDS_Shape& StartShape,
270 const TopoDS_Shape& EndShape)
272 ShapeUpgrade_UnifySameDomain Unifier(aShape);
274 myInitialShape = Unifier.Shape();
276 TopoDS_Wire aStartWire, anEndWire;
277 if (StartShape.ShapeType() == TopAbs_FACE)
279 const TopoDS_Face& StartFace = TopoDS::Face(StartShape);
280 aStartWire = BRepTools::OuterWire(StartFace);
283 aStartWire = TopoDS::Wire(StartShape);
285 if (EndShape.ShapeType() == TopAbs_FACE)
287 const TopoDS_Face& EndFace = TopoDS::Face(EndShape);
288 anEndWire = BRepTools::OuterWire(EndFace);
291 anEndWire = TopoDS::Wire(EndShape);
293 BRepLib_MakeWire MWstart;
294 //TopTools_MapOfShape MapEdges;
295 BRepTools_WireExplorer wexp(aStartWire);
296 for (; wexp.More(); wexp.Next())
298 TopoDS_Shape anEdge = wexp.Current();
299 TopoDS_Shape NewEdge = Unifier.Generated(anEdge);
300 if (!NewEdge.IsNull())
301 MWstart.Add(TopoDS::Edge(NewEdge));
303 myStartWire = MWstart.Wire();
305 BRepLib_MakeWire MWend;
307 for (wexp.Init(anEndWire); wexp.More(); wexp.Next())
309 TopoDS_Shape anEdge = wexp.Current();
310 TopoDS_Shape NewEdge = Unifier.Generated(anEdge);
311 if (!NewEdge.IsNull())
312 MWend.Add(TopoDS::Edge(NewEdge));
314 myEndWire = MWend.Wire();
316 myClosedSection = myStartWire.Closed();
317 myClosedRing = myStartWire.IsSame(myEndWire);
320 //=======================================================================
323 //=======================================================================
325 void BRepOffsetAPI_MiddlePath::Build()
327 TopTools_ListIteratorOfListOfShape itl;
329 TopTools_SequenceOfShape StartVertices;
330 TopTools_MapOfShape EndVertices;
331 TopTools_MapOfShape EndEdges;
332 BRepOffsetAPI_SequenceOfSequenceOfShape SectionsEdges;
334 BRepTools_WireExplorer wexp(myStartWire);
335 TopTools_SequenceOfShape EdgeSeq;
336 for (; wexp.More(); wexp.Next())
338 StartVertices.Append(wexp.CurrentVertex());
339 EdgeSeq.Append(wexp.Current());
341 if (!myClosedSection)
342 StartVertices.Append(wexp.CurrentVertex());
343 SectionsEdges.Append(EdgeSeq);
345 for (wexp.Init(myEndWire); wexp.More(); wexp.Next())
347 EndVertices.Add(wexp.CurrentVertex());
348 EndEdges.Add(wexp.Current());
350 if (!myClosedSection)
351 EndVertices.Add(wexp.CurrentVertex());
354 TopoDS_Iterator itw(myStartWire);
355 for (; itw.More(); itw.Next())
356 myStartWireEdges.Add(itw.Value());
357 for (itw.Initialize(myEndWire); itw.More(); itw.Next())
358 myEndWireEdges.Add(itw.Value());
360 TopTools_IndexedDataMapOfShapeListOfShape VEmap;
361 TopTools_IndexedDataMapOfShapeListOfShape EFmap;
362 TopExp::MapShapesAndAncestors(myInitialShape, TopAbs_VERTEX, TopAbs_EDGE, VEmap);
363 TopExp::MapShapesAndAncestors(myInitialShape, TopAbs_EDGE, TopAbs_FACE, EFmap);
365 TopTools_MapOfShape CurVertices;
367 Standard_Integer i, j, k;
369 TopoDS_Vertex V1, V2, NextVertex;
370 //Initialization of <myPaths>
371 for (i = 1; i <= StartVertices.Length(); i++)
373 TopTools_SequenceOfShape Edges;
374 const TopTools_ListOfShape& LE = VEmap.FindFromKey(StartVertices(i));
375 for (itl.Initialize(LE); itl.More(); itl.Next())
377 anEdge = TopoDS::Edge(itl.Value());
378 if (!myStartWireEdges.Contains(anEdge))
380 TopExp::Vertices(anEdge, V1, V2, Standard_True);
381 if (V1.IsSame(StartVertices(i)))
388 Edges.Append(anEdge);
392 if (!Edges.IsEmpty())
393 myPaths.Append(Edges);
398 //Filling of "myPaths"
399 TopTools_ListOfShape NextVertices;
402 for (i = 1; i <= myPaths.Length(); i++)
404 const TopoDS_Shape& theShape = myPaths(i).Last();
406 TopoDS_Vertex theVertex;
407 if (theShape.ShapeType() == TopAbs_EDGE)
409 theEdge = TopoDS::Edge(theShape);
410 theVertex = TopExp::LastVertex(theEdge, Standard_True);
412 else //last segment of path was punctual
414 theEdge = TopoDS::Edge(myPaths(i)(myPaths(i).Length()-1));
415 theVertex = TopoDS::Vertex(theShape);
418 if (EndVertices.Contains(theVertex))
420 const TopTools_ListOfShape& LE = VEmap.FindFromKey(theVertex);
421 TopTools_MapOfShape NextEdgeCandidates;
422 for (itl.Initialize(LE); itl.More(); itl.Next())
424 anEdge = TopoDS::Edge(itl.Value());
425 if (anEdge.IsSame(theEdge))
427 TopExp::Vertices(anEdge, V1, V2, Standard_True);
428 if (V1.IsSame(theVertex))
435 if (!CurVertices.Contains(NextVertex))
436 NextEdgeCandidates.Add(anEdge);
438 if (!NextEdgeCandidates.IsEmpty())
440 if (NextEdgeCandidates.Extent() > 1)
441 myPaths(i).Append(theVertex); //punctual segment of path
444 TopTools_MapIteratorOfMapOfShape mapit(NextEdgeCandidates);
445 anEdge = TopoDS::Edge(mapit.Key());
446 myPaths(i).Append(anEdge);
447 NextVertex = TopExp::LastVertex(anEdge, Standard_True);
448 NextVertices.Append(NextVertex);
452 if (NextVertices.IsEmpty())
454 for (itl.Initialize(NextVertices); itl.More(); itl.Next())
455 CurVertices.Add(itl.Value());
456 NextVertices.Clear();
461 TopoDS_Compound aCompound, aCmp1;
463 BB.MakeCompound(aCompound);
464 BB.MakeCompound(aCmp1);
465 for (i = 1; i <= myPaths.Length(); i++)
467 TopoDS_Compound aCmp;
468 BB.MakeCompound(aCmp);
469 for (j = 1; j <= myPaths(i).Length(); j++)
470 BB.Add(aCmp, myPaths(i)(j));
473 BB.Add(aCompound, aCmp1);
482 //Building of set of sections
483 Standard_Integer NbE = EdgeSeq.Length();
484 Standard_Integer NbPaths = myPaths.Length();
485 Standard_Integer NbVer = myPaths.Length();
491 for (j = 1; j <= EdgeSeq.Length(); j++)
492 EdgeSeq(j).Nullify();
494 Standard_Boolean ToInsertVertex = Standard_False;
496 for (j = 2; j <= NbVer; j++)
498 if (!EdgeSeq(j-1).IsNull())
501 //for the end of initial shape
502 if (myPaths(j-1).Length() < i)
504 TopoDS_Edge aE1 = TopoDS::Edge(myPaths(j-1)(i-1));
505 TopoDS_Shape LastVer = TopExp::LastVertex(aE1, Standard_True);
506 myPaths(j-1).Append(LastVer);
508 if (myPaths((j<=NbPaths)? j : 1).Length() < i)
510 TopoDS_Edge aE2 = TopoDS::Edge(myPaths((j<=NbPaths)? j : 1)(i-1));
511 TopoDS_Shape LastVer = TopExp::LastVertex(aE2, Standard_True);
512 myPaths((j<=NbPaths)? j : 1).Append(LastVer);
514 //////////////////////////////
518 if (myPaths(j-1)(i).ShapeType() == TopAbs_EDGE)
520 TopoDS_Edge aE1 = TopoDS::Edge(myPaths(j-1)(i));
521 TopoDS_Shape fver = TopExp::FirstVertex(aE1, Standard_True);
522 myPaths(j-1).InsertBefore(i, fver);
524 if (myPaths((j<=NbPaths)? j : 1)(i).ShapeType() == TopAbs_EDGE)
526 TopoDS_Edge aE2 = TopoDS::Edge(myPaths((j<=NbPaths)? j : 1)(i));
527 TopoDS_Shape fver = TopExp::FirstVertex(aE2, Standard_True);
528 myPaths((j<=NbPaths)? j : 1).InsertBefore(i, fver);
530 ToInsertVertex = Standard_False;
534 if (myPaths(j-1)(i).ShapeType() == TopAbs_EDGE)
535 E1 = TopoDS::Edge(myPaths(j-1)(i));
536 if (myPaths((j<=NbPaths)? j : 1)(i).ShapeType() == TopAbs_EDGE)
537 E2 = TopoDS::Edge(myPaths((j<=NbPaths)? j : 1)(i));
538 TopoDS_Edge E12 = TopoDS::Edge(SectionsEdges(i)(j-1));
539 //Find the face on which (E1 or E2) and E12 lie
540 TopoDS_Shape E1orE2 = (E1.IsNull())? E2 : E1;
541 if (E1orE2.IsNull()) //both E1 and E2 are vertices =>
543 EdgeSeq(j-1) = E12; // => proper edge is the edge of previous section between them
546 const TopTools_ListOfShape& LF = EFmap.FindFromKey(E1orE2);
548 for (itl.Initialize(LF); itl.More(); itl.Next())
550 const TopoDS_Shape& aFace = itl.Value();
551 const TopTools_ListOfShape& LF2 = EFmap.FindFromKey(E12);
552 TopTools_ListIteratorOfListOfShape itl2(LF2);
553 for (; itl2.More(); itl2.Next())
555 const TopoDS_Shape& aFace2 = itl2.Value();
556 if (aFace.IsSame(aFace2))
558 theFace = TopoDS::Face(aFace);
562 if (!theFace.IsNull())
566 TopoDS_Vertex PrevVertex = (E1.IsNull())? TopoDS::Vertex(myPaths(j-1)(i))
567 : TopExp::LastVertex(E1, Standard_True);
568 TopoDS_Vertex CurVertex = (E2.IsNull())? TopoDS::Vertex(myPaths((j<=NbPaths)? j : 1)(i))
569 : TopExp::LastVertex(E2, Standard_True);
571 TopoDS_Edge ProperEdge;
572 const TopTools_ListOfShape& LE = VEmap.FindFromKey(PrevVertex);
574 //Standard_Integer LenList = LE.Extent();
576 TopTools_IndexedMapOfShape EdgesOfTheFace;
577 TopExp::MapShapes(theFace, TopAbs_EDGE, EdgesOfTheFace);
578 for (itl.Initialize(LE); itl.More(); itl.Next())
580 anEdge = TopoDS::Edge(itl.Value());
581 TopExp::Vertices(anEdge, V1, V2);
582 if (((V1.IsSame(PrevVertex) && V2.IsSame(CurVertex)) ||
583 (V1.IsSame(CurVertex) && V2.IsSame(PrevVertex))) &&
584 EdgesOfTheFace.Contains(anEdge) && //this condition is for a section of two edges
585 !anEdge.IsSame(E1)) //the last condition is for torus-like shape
592 if ((myPaths(j-1)(i)).ShapeType() == TopAbs_VERTEX &&
593 (myPaths((j<=NbPaths)? j : 1)(i)).ShapeType() == TopAbs_VERTEX)
595 EdgeSeq(j-1) = ProperEdge;
599 TopoDS_Vertex PrevPrevVer = (E1.IsNull())? PrevVertex
600 : TopExp::FirstVertex(E1, Standard_True);
601 TopoDS_Vertex PrevCurVer = (E2.IsNull())? CurVertex
602 : TopExp::FirstVertex(E2, Standard_True);
603 if (ProperEdge.IsNull()) //no connection between these two vertices
605 //Find the face on which E1, E2 and E12 lie
606 //ToInsertVertex = Standard_False;
607 TopTools_ListOfShape ListOneFace;
608 ListOneFace.Append(theFace);
610 if (E1.IsNull() || E2.IsNull())
613 E1 = TopoDS::Edge(myPaths(j-1)(i-1));
615 E2 = TopoDS::Edge(myPaths((j<=NbPaths)? j : 1)(i-1));
616 Standard_Real fpar1, lpar1, fpar2, lpar2;
617 Standard_Real LastPar1, LastPar2;
618 Handle(Geom2d_Curve) PCurve1 = BRep_Tool::CurveOnSurface(E1, theFace, fpar1, lpar1);
619 Handle(Geom2d_Curve) PCurve2 = BRep_Tool::CurveOnSurface(E2, theFace, fpar2, lpar2);
620 if (E1.Orientation() == TopAbs_FORWARD)
621 { LastPar1 = lpar1; }
623 { LastPar1 = fpar1; }
624 if (E2.Orientation() == TopAbs_FORWARD)
625 { LastPar2 = lpar2; }
627 { LastPar2 = fpar2; }
628 gp_Pnt2d FirstPnt2d = PCurve1->Value(LastPar1);
629 gp_Pnt2d LastPnt2d = PCurve2->Value(LastPar2);
630 Handle(Geom_Surface) theSurf = BRep_Tool::Surface(theFace);
631 Handle(Geom2d_Line) theLine = GCE2d_MakeLine(FirstPnt2d, LastPnt2d);
632 Standard_Real len_ne = FirstPnt2d.Distance(LastPnt2d);
633 TopoDS_Edge NewEdge = BRepLib_MakeEdge(theLine, theSurf,
634 PrevVertex, CurVertex,
636 BRepLib::BuildCurve3d(NewEdge);
637 EdgeSeq(j-1) = NewEdge;
638 EFmap.Add(NewEdge, ListOneFace);
643 Standard_Real fpar1, lpar1, fpar2, lpar2;
644 Standard_Real FirstPar1, LastPar1, FirstPar2, LastPar2;
645 Handle(Geom2d_Curve) PCurve1 = BRep_Tool::CurveOnSurface(E1, theFace, fpar1, lpar1);
646 Handle(Geom2d_Curve) PCurve2 = BRep_Tool::CurveOnSurface(E2, theFace, fpar2, lpar2);
647 if (E1.Orientation() == TopAbs_FORWARD)
648 { FirstPar1 = fpar1; LastPar1 = lpar1; }
650 { FirstPar1 = lpar1; LastPar1 = fpar1; }
651 if (E2.Orientation() == TopAbs_FORWARD)
652 { FirstPar2 = fpar2; LastPar2 = lpar2; }
654 { FirstPar2 = lpar2; LastPar2 = fpar2; }
655 gp_Pnt2d FirstPnt2d = PCurve1->Value(LastPar1);
656 gp_Pnt2d LastPnt2d = PCurve2->Value(LastPar2);
657 Handle(Geom_Surface) theSurf = BRep_Tool::Surface(theFace);
658 Handle(Geom2d_Line) theLine = GCE2d_MakeLine(FirstPnt2d, LastPnt2d);
659 Standard_Real len_ne = FirstPnt2d.Distance(LastPnt2d);
660 TopoDS_Edge NewEdge = BRepLib_MakeEdge(theLine, theSurf,
661 PrevVertex, CurVertex,
663 BRepLib::BuildCurve3d(NewEdge);
664 gp_Pnt2d PrevFirstPnt2d = PCurve1->Value(FirstPar1);
665 gp_Pnt2d PrevLastPnt2d = PCurve2->Value(FirstPar2);
666 Handle(Geom2d_Line) Line1 = GCE2d_MakeLine(PrevFirstPnt2d, LastPnt2d);
667 Handle(Geom2d_Line) Line2 = GCE2d_MakeLine(FirstPnt2d, PrevLastPnt2d);
668 Standard_Real len_ne1 = PrevFirstPnt2d.Distance(LastPnt2d);
669 TopoDS_Edge NewEdge1 = BRepLib_MakeEdge(Line1, theSurf,
670 PrevPrevVer, CurVertex,
672 BRepLib::BuildCurve3d(NewEdge1);
673 Standard_Real len_ne2 = FirstPnt2d.Distance(PrevLastPnt2d);
674 TopoDS_Edge NewEdge2 = BRepLib_MakeEdge(Line2, theSurf,
675 PrevVertex, PrevCurVer,
677 BRepLib::BuildCurve3d(NewEdge2);
678 Standard_Boolean good_ne = IsValidEdge(NewEdge, theFace);
679 Standard_Boolean good_ne1 = IsValidEdge(NewEdge1, theFace);
681 GeomAbs_CurveType type_E1 = TypeOfEdge(E1);
682 GeomAbs_CurveType type_E2 = TypeOfEdge(E2);
684 Standard_Integer ChooseEdge = 0;
686 if (!good_ne || type_E1 != type_E2)
688 if (type_E1 == type_E2) //!good_ne
695 else //types are different
697 if (type_E1 == GeomAbs_Line)
699 else if (type_E2 == GeomAbs_Line)
701 else //to be developed later...
708 EdgeSeq(j-1) = NewEdge;
709 EFmap.Add(NewEdge, ListOneFace);
711 else if (ChooseEdge == 1)
713 EdgeSeq(j-1) = NewEdge1;
714 EFmap.Add(NewEdge1, ListOneFace);
715 for (k = 1; k < j-1; k++)
716 EdgeSeq(k).Nullify();
717 for (k = 1; k <= j-1; k++)
719 TopoDS_Edge aLastEdge = TopoDS::Edge(myPaths(k)(i));
720 TopoDS_Shape VertexAsEdge = TopExp::FirstVertex(aLastEdge, Standard_True);
721 myPaths(k).InsertBefore(i, VertexAsEdge);
723 j = 1; //start from beginning
725 else if (ChooseEdge == 2)
727 EdgeSeq(j-1) = NewEdge2;
728 EFmap.Add(NewEdge2, ListOneFace);
729 ToInsertVertex = Standard_True;
731 } //else //E1 is edge
732 } //if (ProperEdge.IsNull())
733 else //connecting edge exists
738 myPaths(j-1).InsertBefore(i, PrevPrevVer);
739 myPaths((j<=NbPaths)? j : 1).InsertBefore(i, PrevCurVer);
744 EdgeSeq(j-1) = ProperEdge;
746 } //for (j = 2; j <= NbVer; j++)
747 SectionsEdges.Append(EdgeSeq);
749 //check for exit from for(;;)
750 Standard_Integer NbEndEdges = 0;
751 for (j = 1; j <= EdgeSeq.Length(); j++)
752 if (EndEdges.Contains(EdgeSeq(j)))
754 if (NbEndEdges == NbE)
761 //final phase: building of middle path
762 Standard_Integer NbSecFaces = SectionsEdges.Length();
763 TopTools_Array1OfShape SecFaces(1, NbSecFaces);
764 for (i = 1; i <= NbSecFaces; i++)
767 for (j = 1; j <= NbE; j++)
769 anEdge = TopoDS::Edge(SectionsEdges(i)(j));
772 if (!myClosedSection)
774 TopExp::Vertices(MW.Wire(), V1, V2);
775 anEdge = BRepLib_MakeEdge(V2, V1);
778 TopoDS_Wire aWire = MW.Wire();
779 BRepLib_MakeFace MF(aWire, Standard_True); //Only plane
781 SecFaces(i) = MF.Face();
786 TColgp_Array1OfPnt Centers(1, NbSecFaces);
787 for (i = 1; i <= NbSecFaces; i++)
789 GProp_GProps Properties;
790 if (SecFaces(i).ShapeType() == TopAbs_FACE)
791 BRepGProp::SurfaceProperties(SecFaces(i), Properties);
793 BRepGProp::LinearProperties(SecFaces(i), Properties);
795 Centers(i) = Properties.CentreOfMass();
798 TopTools_Array1OfShape MidEdges(1, NbSecFaces-1);
799 Standard_Real LinTol = 1.e-5;
800 Standard_Real AngTol = 1.e-7;
802 for (i = 1; i < NbSecFaces; i++)
804 GeomAbs_CurveType TypeOfMidEdge = GeomAbs_OtherCurve;
805 for (j = 1; j <= myPaths.Length(); j++)
807 const TopoDS_Shape& aShape = myPaths(j)(i);
808 if (aShape.ShapeType() == TopAbs_VERTEX)
810 TypeOfMidEdge = GeomAbs_OtherCurve;
813 anEdge = TopoDS::Edge(aShape);
814 GeomAbs_CurveType aType = TypeOfEdge(anEdge);
816 TypeOfMidEdge = aType;
819 if (aType != TypeOfMidEdge)
821 TypeOfMidEdge = GeomAbs_OtherCurve;
826 if (TypeOfMidEdge == GeomAbs_Line)
827 MidEdges(i) = BRepLib_MakeEdge(Centers(i), Centers(i+1));
828 else if (TypeOfMidEdge == GeomAbs_Circle)
831 gp_Dir theDir1, theDir2;
832 Standard_Real theAngle = 0.;
834 Standard_Boolean SimilarArcs = Standard_True;
835 for (j = 1; j <= myPaths.Length(); j++)
837 anEdge = TopoDS::Edge(myPaths(j)(i));
838 Standard_Real fpar, lpar;
839 Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, fpar, lpar);
840 if (aCurve->IsInstance(STANDARD_TYPE(Geom_TrimmedCurve)))
841 aCurve = ((Handle(Geom_TrimmedCurve)&) aCurve)->BasisCurve();
842 Pnt1 = aCurve->Value(fpar);
843 Pnt2 = aCurve->Value(lpar);
844 Handle(Geom_Circle) aCircle = Handle(Geom_Circle)::DownCast(aCurve);
845 gp_Circ aCirc = aCircle->Circ();
848 theAxis = aCirc.Axis();
849 theDir1 = gp_Vec(aCirc.Location(), Pnt1);
850 theDir2 = gp_Vec(aCirc.Location(), Pnt2);
851 theAngle = lpar - fpar;
852 Standard_Real theParam = (anEdge.Orientation() == TopAbs_FORWARD)?
854 aCurve->D1(theParam, Pnt1, theTangent);
855 if (anEdge.Orientation() == TopAbs_REVERSED)
856 theTangent.Reverse();
860 gp_Ax1 anAxis = aCirc.Axis();
862 if (!aLin.Contains(theAxis.Location(), LinTol) ||
863 !anAxis.IsParallel(theAxis, AngTol))
865 SimilarArcs = Standard_False;
868 gp_Dir aDir1 = gp_Vec(aCirc.Location(), Pnt1);
869 gp_Dir aDir2 = gp_Vec(aCirc.Location(), Pnt2);
870 if (!((aDir1.IsEqual(theDir1, AngTol) && aDir2.IsEqual(theDir2, AngTol)) ||
871 (aDir1.IsEqual(theDir2, AngTol) && aDir2.IsEqual(theDir1, AngTol))))
873 SimilarArcs = Standard_False;
880 gp_XYZ AxisLoc = theAxis.Location().XYZ();
881 gp_XYZ AxisDir = theAxis.Direction().XYZ();
882 Standard_Real Parameter = (Centers(i).XYZ() - AxisLoc) * AxisDir;
883 gp_Pnt theCenterOfCirc(AxisLoc + Parameter*AxisDir);
885 gp_Vec Vec1(theCenterOfCirc, Centers(i));
886 gp_Vec Vec2(theCenterOfCirc, Centers(i+1));
888 gp_Dir VecProd = Vec1 ^ Vec2;
889 if (theAxis.Direction() * VecProd < 0.)
893 Standard_Real anAngle = Vec1.AngleWithRef(Vec2, theAxis.Direction());
896 if (Abs(anAngle - theAngle) > AngTol)
898 gp_Ax2 theAx2(theCenterOfCirc, theAxis.Direction(), Vec1);
899 Handle(Geom_Circle) theCircle = GC_MakeCircle(theAx2, Vec1.Magnitude());
901 theCircle->D1( 0., Pnt1, aTangent );
902 if (aTangent * theTangent < 0.)
905 theAx2 = gp_Ax2(theCenterOfCirc, theAxis.Direction(), Vec1);
906 theCircle = GC_MakeCircle(theAx2, Vec1.Magnitude());
908 BRepLib_MakeEdge aME (theCircle, 0., theAngle);
911 MidEdges(i) = aME.IsDone() ?
919 for (i = 1; i < NbSecFaces; i++)
921 if (MidEdges(i).IsNull())
923 for (j = i+1; j < NbSecFaces; j++)
925 if (!MidEdges(j).IsNull())
928 //from i to j-1 all edges are null
929 Handle(TColgp_HArray1OfPnt) thePoints = new TColgp_HArray1OfPnt(1, j-i+1);
930 TColgp_Array1OfVec theTangents(1, j-i+1);
931 Handle(TColStd_HArray1OfBoolean) theFlags = new TColStd_HArray1OfBoolean(1, j-i+1);
932 for (k = i; k <= j; k++)
933 thePoints->SetValue(k-i+1, Centers(k));
934 for (k = i; k <= j; k++)
936 TColgp_SequenceOfPnt PntSeq;
937 for (Standard_Integer indp = 1; indp <= myPaths.Length(); indp++)
942 if (myPaths(indp)(k).ShapeType() == TopAbs_VERTEX)
944 aTangent = TangentOfEdge(myPaths(indp)(k), Standard_True); //at begin
948 if (myPaths(indp)(k-1).ShapeType() == TopAbs_VERTEX)
950 aTangent = TangentOfEdge(myPaths(indp)(k-1), Standard_False); //at end
954 if (myPaths(indp)(k-1).ShapeType() == TopAbs_VERTEX ||
955 myPaths(indp)(k).ShapeType() == TopAbs_VERTEX)
957 gp_Vec Tangent1 = TangentOfEdge(myPaths(indp)(k-1), Standard_False); //at end
958 gp_Vec Tangent2 = TangentOfEdge(myPaths(indp)(k), Standard_True); //at begin
959 aTangent = Tangent1 + Tangent2;
961 aTangent.Normalize();
962 gp_Pnt aPnt(aTangent.XYZ());
965 TColgp_Array1OfPnt PntArray(1, PntSeq.Length());
966 for (Standard_Integer ip = 1; ip <= PntSeq.Length(); ip++)
967 PntArray(ip) = PntSeq(ip);
970 Standard_Real xgap, ygap, zgap;
971 GeomLib::Inertia(PntArray, theBary, xdir, ydir, xgap, ygap, zgap);
972 gp_Vec theTangent(theBary.XYZ());
973 theTangents(k-i+1) = theTangent;
975 theFlags->Init(Standard_True);
977 GeomAPI_Interpolate Interpol(thePoints, Standard_False, LinTol);
978 Interpol.Load(theTangents, theFlags);
980 if (!Interpol.IsDone())
982 cout<<endl<<"Interpolation failed"<<endl;
984 Handle(Geom_Curve) InterCurve = Interpol.Curve();
985 MidEdges(i) = BRepLib_MakeEdge(InterCurve);
990 BRepLib_MakeWire MakeFinalWire;
991 for (i = 1; i < NbSecFaces; i++)
992 if (!MidEdges(i).IsNull())
993 MakeFinalWire.Add(TopoDS::Edge(MidEdges(i)));
995 TopoDS_Wire FinalWire = MakeFinalWire.Wire();
996 myShape = MakeFinalWire.Wire();
1000 TopoDS_Compound aCompound, aCmp1, aCmp2;
1002 BB.MakeCompound(aCompound);
1003 BB.MakeCompound(aCmp1);
1004 BB.MakeCompound(aCmp2);
1005 for (i = 1; i <= myPaths.Length(); i++)
1007 TopoDS_Compound aCmp;
1008 BB.MakeCompound(aCmp);
1009 for (j = 1; j <= myPaths(i).Length(); j++)
1010 BB.Add(aCmp, myPaths(i)(j));
1011 BB.Add(aCmp1, aCmp);
1013 for (i = 1; i <= SectionsEdges.Length(); i++)
1017 for (j = 1; j <= SectionsEdges(i).Length(); j++)
1018 BB.Add(aWire, SectionsEdges(i)(j));
1019 BB.Add(aCmp2, aWire);
1021 BB.Add(aCompound, aCmp1);
1022 BB.Add(aCompound, aCmp2);
1023 BB.Add(aCompound, FinalWire);
1025 myShape = aCompound;