1 // Created on: 1994-06-07
2 // Created by: Bruno DUMORTIER
3 // Copyright (c) 1994-1999 Matra Datavision
4 // Copyright (c) 1999-2012 OPEN CASCADE SAS
6 // The content of this file is subject to the Open CASCADE Technology Public
7 // License Version 6.5 (the "License"). You may not use the content of this file
8 // except in compliance with the License. Please obtain a copy of the License
9 // at http://www.opencascade.org and read it completely before using this file.
11 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
12 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
14 // The Original Code and all software distributed under the License is
15 // distributed on an "AS IS" basis, without warranty of any kind, and the
16 // Initial Developer hereby disclaims all such warranties, including without
17 // limitation, any warranties of merchantability, fitness for a particular
18 // purpose or non-infringement. Please see the License for the specific terms
19 // and conditions governing the rights and limitations under the License.
22 #include <BRepFill_Pipe.ixx>
24 #include <Standard_ErrorHandler.hxx>
26 #include <BRep_Tool.hxx>
27 #include <BRep_Builder.hxx>
28 #include <BRepClass3d_SolidClassifier.hxx>
29 #include <BRepLib_MakeVertex.hxx>
31 #include <GeomFill_CorrectedFrenet.hxx>
32 #include <GeomFill_CurveAndTrihedron.hxx>
34 #include <BRepFill_SectionPlacement.hxx>
35 #include <BRepFill_ShapeLaw.hxx>
36 #include <BRepFill_Edge3DLaw.hxx>
37 #include <BRepFill_Sweep.hxx>
39 #include <GeomAbs_Shape.hxx>
41 #include <TopAbs_ShapeEnum.hxx>
43 #include <TopoDS_Shell.hxx>
44 #include <TopoDS_Solid.hxx>
45 #include <TopoDS_Compound.hxx>
46 #include <TopoDS_Iterator.hxx>
48 #include <Precision.hxx>
49 #include <Standard_NotImplemented.hxx>
51 #include <Geom_TrimmedCurve.hxx>
52 #include <Geom_OffsetCurve.hxx>
53 #include <Geom_BSplineCurve.hxx>
57 static Standard_Boolean Affich = 0;
60 //=======================================================================
61 //function : BRepFill_Pipe
63 //=======================================================================
65 BRepFill_Pipe::BRepFill_Pipe()
72 //=======================================================================
73 //function : BRepFill_Pipe
75 //=======================================================================
77 BRepFill_Pipe::BRepFill_Pipe(const TopoDS_Wire& Spine,
78 const TopoDS_Shape& Profile,
79 const Standard_Boolean KPart)
83 Perform(Spine, Profile, KPart);
88 //=======================================================================
91 //=======================================================================
93 void BRepFill_Pipe::Perform(const TopoDS_Wire& Spine,
94 const TopoDS_Shape& Profile,
95 const Standard_Boolean KPart)
107 BRepTools_WireExplorer wexp;
108 TopoDS_Shape TheProf;
111 Handle(GeomFill_CorrectedFrenet) TLaw =
112 new (GeomFill_CorrectedFrenet) ();
113 Handle(GeomFill_CurveAndTrihedron) Loc =
114 new (GeomFill_CurveAndTrihedron) (TLaw);
115 myLoc = new (BRepFill_Edge3DLaw) (mySpine, Loc);
116 if (myLoc->NbLaw() == 0) {
117 return; // Degenerated case
119 myLoc->TransformInG0Law(); // Set into continuity
121 BRepFill_SectionPlacement Place(myLoc, Profile);
122 myTrsf = Place.Transformation();
124 TopLoc_Location Loc2(myTrsf), Loc1;
125 Loc1 = Profile.Location();
128 TheProf.Location(Loc2.Multiplied(Loc1));
130 // Construct First && Last Shape
131 Handle(GeomFill_LocationLaw) law;
136 Standard_Real first, last;
137 myLoc->Law(1)->GetDomain(first, last);
138 myLoc->Law(1)->D0(first, M, V);
139 fila.SetValues(M(1,1), M(1,2), M(1,3), V.X(),
140 M(2,1), M(2,2), M(2,3), V.Y(),
141 M(3,1), M(3,2), M(3,3), V.Z(),
144 fila.Multiply(myTrsf);
145 TopLoc_Location LocFirst(fila);
147 if ( ! LocFirst.IsIdentity()) {
148 myFirst.Location( LocFirst.Multiplied(myProfile.Location()) );
151 myLoc->Law(myLoc->NbLaw())->GetDomain(first, last);
152 myLoc->Law(myLoc->NbLaw())->D0(last,M, V);
153 // try { // Not good, but there are no other means to test SetValues
154 fila.SetValues(M(1,1), M(1,2), M(1,3), V.X(),
155 M(2,1), M(2,2), M(2,3), V.Y(),
156 M(3,1), M(3,2), M(3,3), V.Z(),
158 fila.Multiply(myTrsf);
159 TopLoc_Location LocLast(fila);
160 if (! myLoc->IsClosed() || LocFirst != LocLast) {
162 if ( ! LocLast.IsIdentity()) {
163 myLast.Location(LocLast.Multiplied(myProfile.Location()) );
171 DBRep::Set("theprof", TheProf);
172 DBRep::Set("thefirst", myFirst);
173 DBRep::Set("thelast" , myLast);
177 myShape = MakeShape(TheProf, myFirst, myLast);
181 //=======================================================================
184 //=======================================================================
186 const TopoDS_Shape& BRepFill_Pipe::Spine() const
191 //=======================================================================
194 //=======================================================================
196 const TopoDS_Shape& BRepFill_Pipe::Profile() const
201 //=======================================================================
204 //=======================================================================
206 const TopoDS_Shape& BRepFill_Pipe::Shape() const
212 //=======================================================================
213 //function : FirstShape
215 //=======================================================================
217 const TopoDS_Shape& BRepFill_Pipe::FirstShape() const
223 //=======================================================================
224 //function : LastShape
226 //=======================================================================
228 const TopoDS_Shape& BRepFill_Pipe::LastShape() const
234 //=======================================================================
237 //=======================================================================
239 TopoDS_Face BRepFill_Pipe::Face(const TopoDS_Edge& ESpine,
240 const TopoDS_Edge& EProfile)
244 if ( BRep_Tool::Degenerated(EProfile))
247 Standard_Integer ii, ispin = 0, iprof = 0, count = 0;
249 // *************************************************
250 // Search if EProfile is an edge of myProfile
251 // *************************************************
252 iprof = FindEdge(myProfile, EProfile, count);
254 if (!iprof) Standard_DomainError::Raise(
255 "BRepFill_Pipe::Face : Edge not in the Profile");
258 // *************************************************
259 // Search if ESpine is an edge of mySpine and find
260 // the index of the corresponding Filler
261 // *************************************************
262 for (ii=1; ii<=myLoc->NbLaw() && (!ispin); ii++)
263 if (ESpine.IsSame(myLoc->Edge(ii))) ispin = ii;
265 if (!ispin) Standard_DomainError::Raise(
266 "BRepFill_Pipe::Edge : Edge not in the Spine");
268 theFace = TopoDS::Face(myFaces->Value(iprof, ispin));
273 //=======================================================================
276 //=======================================================================
277 TopoDS_Edge BRepFill_Pipe::Edge(const TopoDS_Edge& ESpine,
278 const TopoDS_Vertex& VProfile)
280 Standard_Integer ii, ispin = 0, iprof = 0, count = 0;;
282 // *************************************************
283 // Search if VProfile is a Vertex of myProfile
284 // *************************************************
285 iprof = FindVertex(myProfile, VProfile, count);
286 if (!iprof) Standard_DomainError::Raise(
287 "BRepFill_Pipe::Edge : Vertex not in the Profile");
290 // *************************************************
291 // Search if ESpine is an edge of mySpine and find
292 // the index of the corresponding Filler
293 // *************************************************
295 for (ii=1; ii<=myLoc->NbLaw() && (!ispin); ii++)
296 if (ESpine.IsSame(myLoc->Edge(ii))) ispin = ii;
298 if (!ispin) Standard_DomainError::Raise(
299 "BRepFill_Pipe::Edge : Edge not in the Spine");
302 // *************************************************
303 // Generate the corresponding Shape
304 // *************************************************
306 theEdge = TopoDS::Edge(myEdges->Value(iprof, ispin));
313 //=======================================================================
316 //=======================================================================
318 TopoDS_Shape BRepFill_Pipe::Section(const TopoDS_Vertex& VSpine) const
320 TopoDS_Iterator it, itv;
322 Standard_Integer ii, ispin = 0;
324 TopoDS_Shape curSect = myProfile;
326 // *************************************************
327 // Search if ESpine is an edge of mySpine and find
328 // the index of the corresponding Filler
329 // *************************************************
331 // iterate on all the edges of mySpine
332 for (ii=1; ii<=myLoc->NbLaw()+1 && (!ispin); ii++)
333 if (VSpine.IsSame(myLoc->Vertex(ii))) ispin = ii;
335 if (!ispin) Standard_DomainError::Raise(
336 "BRepFill_Pipe::Section : Vertex not in the Spine");
339 TopoDS_Compound Comp;
340 B.MakeCompound(Comp);
341 for (ii=1; ii<=mySections->ColLength(); ii++)
342 B.Add(Comp, mySections->Value(ii, ispin));
347 //=======================================================================
348 //function : PipeLine
349 //purpose : Construct a wire by sweeping of a point
350 //=======================================================================
352 TopoDS_Wire BRepFill_Pipe::PipeLine(const gp_Pnt& Point) const
359 BRepLib_MakeVertex MkV(P);
360 Handle(BRepFill_ShapeLaw) Section =
361 new (BRepFill_ShapeLaw) (MkV.Vertex());
364 BRepFill_Sweep MkSw(Section, myLoc, Standard_True);
365 MkSw.Build( BRepFill_Modified, GeomFill_Location, GeomAbs_C2, myDegmax, mySegmax );
366 TopoDS_Shape aLocalShape = MkSw.Shape();
367 return TopoDS::Wire(aLocalShape);
368 // return TopoDS::Wire(MkSw.Shape());
371 //=======================================================================
372 //function : MakeShape
374 //=======================================================================
376 TopoDS_Shape BRepFill_Pipe::MakeShape(const TopoDS_Shape& S,
377 const TopoDS_Shape& FirstShape,
378 const TopoDS_Shape& LastShape)
382 Standard_Boolean explode = Standard_False;
383 TopoDS_Shape TheS, TheFirst, TheLast;
384 Standard_Integer InitialLength = 0;
386 TheFirst = FirstShape;
388 if (! myFaces.IsNull()) InitialLength = myFaces->ColLength();
390 // there are two kinds of generation
391 // 1. generate with S from each Filler (Vertex, Edge)
392 // 2. call MakeShape recursively on the subshapes of S
394 // explode is True in the second case
396 // create the result empty
398 switch (S.ShapeType()) {
402 B.MakeWire(TopoDS::Wire(result));
409 B.MakeShell(TopoDS::Shell(result));
412 W.Closed(S.Closed());
414 if (!FirstShape.IsNull()) {
416 B.Add(W, FirstShape);
417 W.Closed(FirstShape.Closed());
420 if (!LastShape.IsNull()) {
423 W.Closed(LastShape.Closed());
430 B.MakeShell(TopoDS::Shell(result));
435 B.MakeShell(TopoDS::Shell(result));
436 explode = Standard_True;
437 if ( !mySpine.Closed() && !TheFirst.IsNull()) {
438 B.Add(result, TheFirst.Reversed());
445 B.MakeCompSolid(TopoDS::CompSolid(result));
446 explode = Standard_True;
451 case TopAbs_COMPSOLID :
452 Standard_DomainError::Raise("BRepFill_Pipe::SOLID or COMPSOLID");
455 case TopAbs_COMPOUND :
457 B.MakeCompound(TopoDS::Compound(result));
458 explode = Standard_True;
467 TopoDS_Iterator itFirst, itLast;
468 TopoDS_Shape first, last;
469 if (!TheFirst.IsNull()) itFirst.Initialize(TheFirst);
470 if (!TheLast.IsNull()) itLast.Initialize(TheLast);
472 for (TopoDS_Iterator it(S); it.More(); it.Next()) {
473 if (!TheFirst.IsNull()) first = itFirst.Value();
474 if (!TheLast.IsNull()) last = itLast.Value();
475 if (TheS.ShapeType() == TopAbs_FACE )
476 MakeShape(it.Value(), first, last);
478 B.Add(result,MakeShape(it.Value(), first, last));
480 if (!TheFirst.IsNull()) itFirst.Next();
481 if (!TheLast.IsNull()) itLast.Next();
486 if (TheS.ShapeType() == TopAbs_VERTEX ) {
487 Handle(BRepFill_ShapeLaw) Section =
488 new (BRepFill_ShapeLaw) (TopoDS::Vertex(TheS));
489 BRepFill_Sweep MkSw(Section, myLoc, Standard_True);
490 MkSw.Build( BRepFill_Modified, GeomFill_Location, GeomAbs_C2, myDegmax, mySegmax );
491 result = MkSw.Shape();
494 if (TheS.ShapeType() == TopAbs_WIRE ) {
495 Handle(BRepFill_ShapeLaw) Section =
496 new (BRepFill_ShapeLaw) (TopoDS::Wire(TheS));
497 BRepFill_Sweep MkSw(Section, myLoc, Standard_True);
498 MkSw.SetBounds(TopoDS::Wire(TheFirst),
499 TopoDS::Wire(TheLast));
500 MkSw.Build( BRepFill_Modified, GeomFill_Location, GeomAbs_C2, myDegmax, mySegmax );
501 result = MkSw.Shape();
503 // Labeling of elements
504 if (mySections.IsNull()) {
505 myFaces = MkSw.SubShape();
506 mySections = MkSw.Sections();
507 myEdges = MkSw.InterFaces();
510 Handle(TopTools_HArray2OfShape) Aux, Somme;
511 Standard_Integer length;
512 Standard_Integer ii, jj, kk;
514 Aux = MkSw.SubShape();
515 length = Aux->ColLength() + myFaces->ColLength();
516 Somme = new (TopTools_HArray2OfShape) (1, length, 1,
518 for (jj=1; jj<=myFaces->RowLength(); jj++) {
519 for (ii=1; ii<=myFaces->ColLength(); ii++)
520 Somme->SetValue(ii, jj, myFaces->Value(ii, jj));
522 for (kk=1, ii=myFaces->ColLength()+1;
523 kk <=Aux->ColLength(); kk++, ii++)
524 Somme->SetValue(ii, jj, Aux->Value(kk, jj));
529 Aux = MkSw.Sections();
530 length = Aux->ColLength() + mySections->ColLength();
531 Somme = new (TopTools_HArray2OfShape) (1, length, 1,
533 for (jj=1; jj<=mySections->RowLength(); jj++) {
534 for (ii=1; ii<=mySections->ColLength(); ii++)
535 Somme->SetValue(ii, jj, mySections->Value(ii, jj));
537 for (kk=1, ii=mySections->ColLength()+1;
538 kk <=Aux->ColLength(); kk++, ii++)
539 Somme->SetValue(ii, jj, Aux->Value(kk, jj));
543 Aux = MkSw.InterFaces();
544 length = Aux->ColLength() + myEdges->ColLength();
545 Somme = new (TopTools_HArray2OfShape) (1, length, 1,
547 for (jj=1; jj<=myEdges->RowLength(); jj++) {
548 for (ii=1; ii<=myEdges->ColLength(); ii++)
549 Somme->SetValue(ii, jj, myEdges->Value(ii, jj));
551 for (kk=1, ii=myEdges->ColLength()+1;
552 kk <=Aux->ColLength(); kk++, ii++)
553 Somme->SetValue(ii, jj, Aux->Value(kk, jj));
560 if ( TheS.ShapeType() == TopAbs_FACE ) {
561 Standard_Integer ii, jj;
563 for (ii=InitialLength+1; ii<=myFaces->ColLength(); ii++) {
564 for (jj=1; jj<=myFaces->RowLength(); jj++) {
565 F = TopoDS::Face(myFaces->Value(ii, jj));
566 if (!F.IsNull()) B.Add(result, F);
570 if ( !mySpine.Closed()) {
571 // if Spine is not closed
572 // add the last face of the solid
573 B.Add(result, TopoDS::Face(TheLast));
580 result.Closed(Standard_True);
581 BS.Add(solid,TopoDS::Shell(result));
583 BRepClass3d_SolidClassifier SC(solid);
584 SC.PerformInfinitePoint(Precision::Confusion());
585 if ( SC.State() == TopAbs_IN) {
587 TopoDS_Shape aLocalShape = result.Reversed();
588 BS.Add(solid,TopoDS::Shell(aLocalShape));
589 // BS.Add(solid,TopoDS::Shell(result.Reversed()));
599 //============================================================================
600 //function : FindEdge
601 //purpose : Find the number of edge corresponding to the edge of the profile.
602 //============================================================================
604 Standard_Integer BRepFill_Pipe::FindEdge(const TopoDS_Shape& S,
605 const TopoDS_Edge& E,
606 Standard_Integer& InitialLength) const
608 Standard_Integer result = 0;
610 switch (S.ShapeType()) {
615 if (S.IsSame(E)) result = InitialLength;
621 Standard_Integer ii = InitialLength+1;
622 Handle(BRepFill_ShapeLaw) Section =
623 new (BRepFill_ShapeLaw) (TopoDS::Wire(S), Standard_False);
624 InitialLength += Section->NbLaw();
626 for (; (ii<=InitialLength) && (!result); ii++) {
627 if (E.IsSame(Section->Edge(ii)) ) result = ii;
634 case TopAbs_COMPOUND :
636 for (TopoDS_Iterator it(S); it.More() && (!result); it.Next())
637 result = FindEdge(it.Value(), E, InitialLength );
642 case TopAbs_COMPSOLID :
643 Standard_DomainError::Raise("BRepFill_Pipe::SOLID or COMPSOLID");
652 //=======================================================================
653 //function : FindVertex
654 //purpose : Find the number of edge corresponding to an edge of the profile.
655 //=======================================================================
657 Standard_Integer BRepFill_Pipe::FindVertex(const TopoDS_Shape& S,
658 const TopoDS_Vertex& V,
659 Standard_Integer& InitialLength) const
661 Standard_Integer result = 0;
663 switch (S.ShapeType()) {
667 if (S.IsSame(V)) result = InitialLength;
673 TopoDS_Vertex VF, VL;
674 TopExp::Vertices(TopoDS::Edge(S), VF, VL);
675 if (S.Orientation() == TopAbs_REVERSED) {
677 aux = VF; VF = VL; VL = aux;
679 if (VF.IsSame(V)) result = InitialLength+1;
680 else if (VL.IsSame(V)) result = InitialLength+2;
687 Standard_Integer ii = InitialLength+1;
688 Handle(BRepFill_ShapeLaw) Section =
689 new (BRepFill_ShapeLaw) (TopoDS::Wire(S), Standard_False);
690 InitialLength += Section->NbLaw()+1;
692 for (; (ii<=InitialLength) && (!result); ii++) {
693 if (V.IsSame(Section->Vertex(ii, 0.)) ) result = ii;
700 case TopAbs_COMPOUND :
702 for (TopoDS_Iterator it(S); it.More() && (!result); it.Next())
703 result = FindVertex(it.Value(), V, InitialLength);
708 case TopAbs_COMPSOLID :
709 Standard_DomainError::Raise("BRepFill_Pipe::SOLID or COMPSOLID");
718 //=======================================================================
719 //function : DefineRealSegmax
720 //purpose : Defines the real number of segments
721 // required in the case of bspline spine
722 //=======================================================================
724 void BRepFill_Pipe::DefineRealSegmax()
726 Standard_Integer RealSegmax = 0;
728 TopoDS_Iterator iter(mySpine);
729 for (; iter.More(); iter.Next())
731 TopoDS_Edge E = TopoDS::Edge(iter.Value());
732 Standard_Real first, last;
733 Handle(Geom_Curve) C = BRep_Tool::Curve( E, first, last );
736 while (C->DynamicType() == STANDARD_TYPE(Geom_TrimmedCurve) ||
737 C->DynamicType() == STANDARD_TYPE(Geom_OffsetCurve))
739 if (C->DynamicType() == STANDARD_TYPE(Geom_TrimmedCurve))
740 C = (*((Handle(Geom_TrimmedCurve)*)&C))->BasisCurve();
741 if (C->DynamicType() == STANDARD_TYPE(Geom_OffsetCurve))
742 C = (*((Handle(Geom_OffsetCurve)*)&C))->BasisCurve();
744 if (C->DynamicType() == STANDARD_TYPE(Geom_BSplineCurve))
746 const Handle(Geom_BSplineCurve)& BC = *((Handle(Geom_BSplineCurve)*)&C);
747 Standard_Integer NbKnots = BC->NbKnots();
748 Standard_Integer RealNbKnots = NbKnots;
749 if (first > BC->FirstParameter())
751 Standard_Integer I1, I2;
752 BC->LocateU( first, Precision::PConfusion(), I1, I2 );
755 if (last < BC->LastParameter())
757 Standard_Integer I1, I2;
758 BC->LocateU( last, Precision::PConfusion(), I1, I2 );
759 RealNbKnots -= NbKnots-I2;
761 RealSegmax += RealNbKnots-1;
765 if (mySegmax < RealSegmax)
766 mySegmax = RealSegmax;