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