Loading files
3d097a032This file is pinned to the selected release. Download the original to open it in your design tool.
// Created on: 1998-07-22
// Created by: Philippe MANGIN
// Copyright (c) 1998-1999 Matra Datavision
// Copyright (c) 1999-2014 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#include <BRep_Builder.hxx>
#include <BRep_Tool.hxx>
#include <BRepAdaptor_CompCurve.hxx>
#include <BRepBuilderAPI_Copy.hxx>
#include <BRepBuilderAPI_Transform.hxx>
#include <BRepClass3d_SolidClassifier.hxx>
#include <BRepFill.hxx>
#include <BRepFill_ACRLaw.hxx>
#include <BRepFill_CompatibleWires.hxx>
#include <BRepFill_Edge3DLaw.hxx>
#include <BRepFill_EdgeOnSurfLaw.hxx>
#include <BRepFill_LocationLaw.hxx>
#include <BRepFill_NSections.hxx>
#include <BRepFill_PipeShell.hxx>
#include <BRepFill_Section.hxx>
#include <BRepFill_SectionLaw.hxx>
#include <BRepFill_SectionPlacement.hxx>
#include <BRepFill_ShapeLaw.hxx>
#include <BRepFill_Sweep.hxx>
#include <BRepGProp.hxx>
#include <BRepLib_MakeFace.hxx>
#include <GeomAdaptor_Surface.hxx>
#include <GeomFill_ConstantBiNormal.hxx>
#include <GeomFill_CorrectedFrenet.hxx>
#include <GeomFill_CurveAndTrihedron.hxx>
#include <GeomFill_DiscreteTrihedron.hxx>
#include <GeomFill_Fixed.hxx>
#include <GeomFill_Frenet.hxx>
#include <GeomFill_GuideTrihedronAC.hxx>
#include <GeomFill_GuideTrihedronPlan.hxx>
#include <GeomFill_LocationGuide.hxx>
#include <GeomFill_SectionLaw.hxx>
#include <GeomFill_TrihedronLaw.hxx>
#include <gp_Ax2.hxx>
#include <gp_Dir.hxx>
#include <gp_Trsf.hxx>
#include <gp_Vec.hxx>
#include <GProp_GProps.hxx>
#include <IntCurveSurface_HInter.hxx>
#include <IntCurveSurface_IntersectionPoint.hxx>
#include <Law_Interpol.hxx>
#include <Precision.hxx>
#include <Standard_ConstructionError.hxx>
#include <Standard_NotImplemented.hxx>
#include <Standard_Type.hxx>
#include <StdFail_NotDone.hxx>
#include <gp_Pnt2d.hxx>
#include <NCollection_Array1.hxx>
#include <NCollection_HArray1.hxx>
#include <Standard_Integer.hxx>
#include <NCollection_Sequence.hxx>
#include <TopExp.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Iterator.hxx>
#include <TopoDS_Shape.hxx>
#include <TopoDS_Shell.hxx>
#include <TopoDS_Solid.hxx>
#include <TopoDS_Vertex.hxx>
#include <TopoDS_Wire.hxx>
#include <cstdio>
IMPLEMENT_STANDARD_RTTIEXT(BRepFill_PipeShell, Standard_Transient)
// Specification Guide
#include <NCollection_List.hxx>
#include <TopTools_ShapeMapHasher.hxx>
#include <NCollection_IndexedDataMap.hxx>
#include <NCollection_DataMap.hxx>
static bool BuildBoundaries(const BRepFill_Sweep& theSweep,
const occ::handle<BRepFill_SectionLaw>& theSection,
TopoDS_Shape& theBottom,
TopoDS_Shape& theTop);
//=======================================================================
// function : ComputeSection
// purpose : Construct an intermediary section
//=======================================================================
static bool ComputeSection(const TopoDS_Wire& W1,
const TopoDS_Wire& W2,
const double p1,
const double p2,
TopoDS_Wire& Wres)
{
NCollection_Sequence<double> SR;
NCollection_Sequence<TopoDS_Shape> SSh;
SR.Clear();
SR.Append(0.);
SR.Append(1.);
SSh.Clear();
SSh.Append(W1);
SSh.Append(W2);
BRepFill_CompatibleWires CW(SSh);
CW.SetPercent(0.1);
CW.Perform();
if (!CW.IsDone())
{
throw StdFail_NotDone("Uncompatible wires");
}
NCollection_Sequence<gp_Trsf> EmptyTrsfs;
occ::handle<BRepFill_NSections> SL = new (BRepFill_NSections)(CW.Shape(), EmptyTrsfs, SR, 0., 1.);
double US = p1 / (p1 + p2);
SL->D0(US, Wres);
return true;
}
//=======================================================================
// function : PerformTransition
// purpose : Modify a law of location depending on Transition
//=======================================================================
static void PerformTransition(const BRepFill_TransitionStyle Mode,
occ::handle<BRepFill_LocationLaw>& Loc,
const double angmin)
{
if (!Loc.IsNull())
{
Loc->DeleteTransform();
if (Mode == BRepFill_Modified)
{
Loc->TransformInG0Law();
}
else
{
Loc->TransformInCompatibleLaw(angmin);
}
}
}
//=======================================================================
// function : PerformPlan
// purpose : Construct a plane of filling if exists
//=======================================================================
static bool PerformPlan(TopoDS_Shape& S)
{
bool isDegen = true;
TopExp_Explorer explo(S, TopAbs_EDGE);
for (; explo.More(); explo.Next())
{
const TopoDS_Edge& anEdge = TopoDS::Edge(explo.Current());
if (!BRep_Tool::Degenerated(anEdge))
{
isDegen = false;
}
}
if (isDegen)
{
S.Nullify();
return true;
}
TopoDS_Wire W = TopoDS::Wire(S);
bool Ok = false;
if (!W.IsNull())
{
BRepLib_MakeFace mkplan(W, true);
if (mkplan.IsDone())
{
S = mkplan.Face();
Ok = true;
}
}
return Ok;
}
//=================================================================================================
static bool IsSameOriented(const TopoDS_Shape& theFace, const TopoDS_Shape& theShell)
{
NCollection_IndexedDataMap<TopoDS_Shape, NCollection_List<TopoDS_Shape>, TopTools_ShapeMapHasher>
anEdgeFaceMap;
TopExp::MapShapesAndAncestors(theShell, TopAbs_EDGE, TopAbs_FACE, anEdgeFaceMap);
for (TopExp_Explorer aFaceExplorer(theFace, TopAbs_EDGE); aFaceExplorer.More();
aFaceExplorer.Next())
{
const TopoDS_Shape& aCurrentEdge = aFaceExplorer.Current();
if (!anEdgeFaceMap.Contains(aCurrentEdge))
{
continue;
}
const TopAbs_Orientation aCurrentEdgeOrientation = aCurrentEdge.Orientation();
const TopoDS_Shape& anAdjFace = anEdgeFaceMap.FindFromKey(aCurrentEdge).First();
for (TopExp_Explorer anAdjFaceExplorer(anAdjFace, TopAbs_EDGE); anAdjFaceExplorer.More();
anAdjFaceExplorer.Next())
{
// IsSame compares TShape and Location only; orientation may differ.
const TopoDS_Shape& anAdjEdge = anAdjFaceExplorer.Current();
if (anAdjEdge.IsSame(aCurrentEdge))
{
return aCurrentEdgeOrientation != anAdjEdge.Orientation();
}
}
}
// No shared edge found. Orientation cannot be determined reliably and this
// should not happen for valid input. Preserve the current face orientation
// instead of reporting an opposite orientation and forcing a reversal.
return true;
}
//=================================================================================================
BRepFill_PipeShell::BRepFill_PipeShell(const TopoDS_Wire& Spine)
: mySpine(Spine),
myForceApproxC1(false),
myIsAutomaticLaw(false),
myTrihedron(GeomFill_IsCorrectedFrenet),
myTransition(BRepFill_Modified),
myStatus(GeomFill_PipeOk),
myIsBuildHistory(true)
{
myLocation.Nullify();
mySection.Nullify();
myLaw.Nullify();
SetTolerance();
myMaxDegree = 11;
myMaxSegments = 100;
// Attention to closed non-declared wire !
if (!mySpine.Closed())
{
TopoDS_Vertex Vf, Vl;
TopExp::Vertices(mySpine, Vf, Vl);
if (Vf.IsSame(Vl))
{
mySpine.Closed(true);
}
}
}
//=======================================================================
// function : Set
// purpose : Define a law of Frenet (Correct)
//=======================================================================
void BRepFill_PipeShell::Set(const bool IsFrenet)
{
occ::handle<GeomFill_TrihedronLaw> TLaw;
if (IsFrenet)
{
myTrihedron = GeomFill_IsFrenet;
TLaw = new (GeomFill_Frenet)();
}
else
{
myTrihedron = GeomFill_IsFrenet;
TLaw = new (GeomFill_CorrectedFrenet)();
}
occ::handle<GeomFill_CurveAndTrihedron> Loc = new (GeomFill_CurveAndTrihedron)(TLaw);
myLocation = new (BRepFill_Edge3DLaw)(mySpine, Loc);
mySection.Nullify(); // It is required to relocalize sections.
}
//=======================================================================
// function : SetDiscrete
// purpose : Define a law of Discrete Trihedron
//=======================================================================
void BRepFill_PipeShell::SetDiscrete()
{
occ::handle<GeomFill_TrihedronLaw> TLaw;
myTrihedron = GeomFill_IsDiscreteTrihedron;
TLaw = new (GeomFill_DiscreteTrihedron)();
occ::handle<GeomFill_CurveAndTrihedron> Loc = new (GeomFill_CurveAndTrihedron)(TLaw);
myLocation = new (BRepFill_Edge3DLaw)(mySpine, Loc);
mySection.Nullify(); // It is required to relocalize sections.
}
//=================================================================================================
void BRepFill_PipeShell::Set(const gp_Ax2& Axe)
{
myTrihedron = GeomFill_IsFixed;
gp_Vec V1, V2;
V1.SetXYZ(Axe.Direction().XYZ());
V2.SetXYZ(Axe.XDirection().XYZ());
occ::handle<GeomFill_Fixed> TLaw = new (GeomFill_Fixed)(V1, V2);
occ::handle<GeomFill_CurveAndTrihedron> Loc = new (GeomFill_CurveAndTrihedron)(TLaw);
myLocation = new (BRepFill_Edge3DLaw)(mySpine, Loc);
mySection.Nullify(); // It is required to relocalize sections.
}
//=======================================================================
// function : Set
// purpose : Construct a law of location of binormal fixed type
//=======================================================================
void BRepFill_PipeShell::Set(const gp_Dir& BiNormal)
{
myTrihedron = GeomFill_IsConstantNormal;
occ::handle<GeomFill_ConstantBiNormal> TLaw = new (GeomFill_ConstantBiNormal)(BiNormal);
occ::handle<GeomFill_CurveAndTrihedron> Loc = new (GeomFill_CurveAndTrihedron)(TLaw);
myLocation = new (BRepFill_Edge3DLaw)(mySpine, Loc);
mySection.Nullify(); // Il faut relocaliser les sections.
}
//=======================================================================
// function : Set
// purpose : Construct a law of location of Darboux type
//=======================================================================
bool BRepFill_PipeShell::Set(const TopoDS_Shape& SpineSupport)
{
bool B;
// A special law of location is required
occ::handle<BRepFill_EdgeOnSurfLaw> loc = new (BRepFill_EdgeOnSurfLaw)(mySpine, SpineSupport);
B = loc->HasResult();
if (B)
{
myLocation = loc;
myTrihedron = GeomFill_IsDarboux;
mySection.Nullify(); // It is required to relocalize the sections.
}
return B;
}
//=======================================================================
// function : Set
// purpose : Defines a lawv with help of a guided contour
//=======================================================================
void BRepFill_PipeShell::Set(const TopoDS_Wire& AuxiliarySpine,
const bool CurvilinearEquivalence,
const BRepFill_TypeOfContact KeepContact)
{
// Reorganization of the guide (pb of orientation and origin)
TopoDS_Wire TheGuide;
TheGuide = AuxiliarySpine;
bool SpClose = mySpine.Closed(), GuideClose = AuxiliarySpine.Closed();
if (KeepContact == BRepFill_ContactOnBorder)
{
myIsAutomaticLaw = true;
}
if (!SpClose && !GuideClose)
{
// Case open reorientation of the guide
TopoDS_Wire sp = mySpine;
NCollection_Sequence<TopoDS_Shape> Seq;
Seq.Append(sp);
Seq.Append(TheGuide);
BRepFill_CompatibleWires CW(Seq);
CW.SetPercent(0.1);
CW.Perform();
if (!CW.IsDone())
{
throw StdFail_NotDone("Uncompatible wires");
}
TheGuide = TopoDS::Wire(CW.Shape().Value(2));
}
else if (GuideClose)
{
// Case guide closed : Determination of the origin
// & reorientation of the guide
gp_Vec Dir;
gp_Pnt SpOr;
if (!SpClose)
{
TopoDS_Vertex Vf, Vl;
gp_Pnt P;
TopExp::Vertices(mySpine, Vf, Vl);
SpOr = BRep_Tool::Pnt(Vf);
P = BRep_Tool::Pnt(Vl);
gp_Vec V(P, SpOr);
SpOr.BaryCenter(0.5, P, 0.5);
Dir = V;
}
else
{
BRepAdaptor_CompCurve BC(mySpine);
BC.D1(0, SpOr, Dir);
}
BRepFill::SearchOrigin(TheGuide, SpOr, Dir, 100 * myTol3d);
}
// transform the guide in a single curve
occ::handle<BRepAdaptor_CompCurve> Guide = new (BRepAdaptor_CompCurve)(TheGuide);
if (CurvilinearEquivalence)
{ // trihedron by curvilinear reduced abscissa
if (KeepContact == BRepFill_Contact || KeepContact == BRepFill_ContactOnBorder)
{
myTrihedron = GeomFill_IsGuideACWithContact; // with rotation
}
else
{
myTrihedron = GeomFill_IsGuideAC; // without rotation
}
occ::handle<GeomFill_GuideTrihedronAC> TLaw = new (GeomFill_GuideTrihedronAC)(Guide);
occ::handle<GeomFill_LocationGuide> Loc = new (GeomFill_LocationGuide)(TLaw);
myLocation = new (BRepFill_ACRLaw)(mySpine, Loc);
}
else
{ // trihedron by plane
if (KeepContact == BRepFill_Contact || KeepContact == BRepFill_ContactOnBorder)
{
myTrihedron = GeomFill_IsGuidePlanWithContact; // with rotation
}
else
{
myTrihedron = GeomFill_IsGuidePlan; // without rotation
}
occ::handle<GeomFill_GuideTrihedronPlan> TLaw = new (GeomFill_GuideTrihedronPlan)(Guide);
occ::handle<GeomFill_LocationGuide> Loc = new (GeomFill_LocationGuide)(TLaw);
myLocation = new (BRepFill_Edge3DLaw)(mySpine, Loc);
}
mySection.Nullify(); // It is required to relocalize the sections.
}
//=================================================================================================
void BRepFill_PipeShell::SetMaxDegree(const int NewMaxDegree)
{
myMaxDegree = NewMaxDegree;
}
//=================================================================================================
void BRepFill_PipeShell::SetMaxSegments(const int NewMaxSegments)
{
myMaxSegments = NewMaxSegments;
}
//=======================================================================
// function : SetForceApproxC1
// purpose : Set the flag that indicates attempt to approximate
// a C1-continuous surface if a swept surface proved
// to be C0.
//=======================================================================
void BRepFill_PipeShell::SetForceApproxC1(const bool ForceApproxC1)
{
myForceApproxC1 = ForceApproxC1;
}
//=================================================================================================
void BRepFill_PipeShell::Add(const TopoDS_Shape& Profile,
const bool WithContact,
const bool WithCorrection)
{
TopoDS_Vertex V;
V.Nullify();
Add(Profile, V, WithContact, WithCorrection);
ResetLoc();
}
//=================================================================================================
void BRepFill_PipeShell::Add(const TopoDS_Shape& Profile,
const TopoDS_Vertex& Location,
const bool WithContact,
const bool WithCorrection)
{
DeleteProfile(Profile); // No duplication
if (myIsAutomaticLaw)
{
mySeq.Clear();
BRepFill_Section S(Profile, Location, WithContact, WithCorrection);
S.Set(true);
mySeq.Append(S);
mySection.Nullify();
ResetLoc();
occ::handle<GeomFill_LocationGuide> Loc =
occ::down_cast<GeomFill_LocationGuide>(myLocation->Law(1));
occ::handle<NCollection_HArray1<gp_Pnt2d>> ParAndRad;
Loc->ComputeAutomaticLaw(ParAndRad);
// Compuite initial width of section (this will be 1.)
GProp_GProps GlobalProps;
BRepGProp::LinearProperties(Profile, GlobalProps);
gp_Pnt BaryCenter = GlobalProps.CentreOfMass();
TopoDS_Face ProfileFace = BRepLib_MakeFace(TopoDS::Wire(Profile), true); // only plane
occ::handle<Geom_Surface> thePlane = BRep_Tool::Surface(ProfileFace);
occ::handle<GeomAdaptor_Surface> GAHplane = new GeomAdaptor_Surface(thePlane);
IntCurveSurface_HInter Intersector;
occ::handle<Adaptor3d_Curve> aHCurve[2];
aHCurve[0] = Loc->GetCurve();
aHCurve[1] = Loc->Guide();
gp_Pnt PointsOnSpines[2];
int i, j;
for (i = 0; i < 2; i++)
{
Intersector.Perform(aHCurve[i], GAHplane);
double MinDist = RealLast();
for (j = 1; j <= Intersector.NbPoints(); j++)
{
gp_Pnt aPint = Intersector.Point(j).Pnt();
double aDist = BaryCenter.Distance(aPint);
if (aDist < MinDist)
{
MinDist = aDist;
PointsOnSpines[i] = aPint;
}
}
}
// Correct <ParAndRad> according to <InitialWidth>
double InitialWidth = PointsOnSpines[0].Distance(PointsOnSpines[1]);
int NbParRad = ParAndRad->Upper();
for (i = 1; i <= NbParRad; i++)
{
gp_Pnt2d aParRad = ParAndRad->Value(i);
aParRad.SetY(aParRad.Y() / InitialWidth);
ParAndRad->SetValue(i, aParRad);
}
myLaw = new Law_Interpol();
bool IsPeriodic =
(std::abs(ParAndRad->Value(1).Y() - ParAndRad->Value(NbParRad).Y()) < Precision::Confusion());
(occ::down_cast<Law_Interpol>(myLaw))->Set(ParAndRad->Array1(), IsPeriodic);
}
else
{
BRepFill_Section S(Profile, Location, WithContact, WithCorrection);
mySeq.Append(S);
mySection.Nullify();
ResetLoc();
}
}
//=======================================================================
// function : SetLaw
// purpose : Section + law of homothety
//=======================================================================
void BRepFill_PipeShell::SetLaw(const TopoDS_Shape& Profile,
const occ::handle<Law_Function>& L,
const bool WithContact,
const bool WithCorrection)
{
TopoDS_Vertex V;
V.Nullify();
SetLaw(Profile, L, V, WithContact, WithCorrection);
ResetLoc();
}
//=======================================================================
// function : SetLaw
// purpose : Section + Law of homothety
//=======================================================================
void BRepFill_PipeShell::SetLaw(const TopoDS_Shape& Profile,
const occ::handle<Law_Function>& L,
const TopoDS_Vertex& Location,
const bool WithContact,
const bool WithCorrection)
{
mySeq.Clear();
BRepFill_Section S(Profile, Location, WithContact, WithCorrection);
S.Set(true);
mySeq.Append(S);
myLaw = L;
mySection.Nullify();
ResetLoc();
}
//=================================================================================================
void BRepFill_PipeShell::DeleteProfile(const TopoDS_Shape& Profile)
{
bool Trouve = false;
int ii;
for (ii = 1; ii <= mySeq.Length() && !Trouve; ii++)
{
const TopoDS_Shape& aSection = mySeq.Value(ii).OriginalShape();
if (Profile.IsSame(aSection))
{
Trouve = true;
mySeq.Remove(ii);
}
}
if (Trouve)
{
mySection.Nullify();
}
ResetLoc();
}
//=================================================================================================
bool BRepFill_PipeShell::IsReady() const
{
return (mySeq.Length() != 0);
}
//=================================================================================================
GeomFill_PipeError BRepFill_PipeShell::GetStatus() const
{
return myStatus;
}
//=================================================================================================
void BRepFill_PipeShell::SetTolerance(const double Tol3d,
const double BoundTol,
const double TolAngular)
{
myTol3d = Tol3d;
myBoundTol = BoundTol;
myTolAngular = TolAngular;
}
//=======================================================================
// function : SetTransition
// purpose : Defines the mode of processing of corners
//=======================================================================
void BRepFill_PipeShell::SetTransition(const BRepFill_TransitionStyle Mode,
const double Angmin,
const double Angmax)
{
if (myTransition != Mode)
{
mySection.Nullify(); // It is required to relocalize the sections.
}
myTransition = Mode;
angmin = Angmin;
angmax = Angmax;
}
//=================================================================================================
void BRepFill_PipeShell::Simulate(const int N, NCollection_List<TopoDS_Shape>& List)
{
// Preparation
Prepare();
List.Clear();
double First, Last, Length, Delta, U, US, DeltaS, FirstS;
int ii, NbL = myLocation->NbLaw();
bool Finis = false;
TopoDS_Shape W;
// Calculate the parameters of digitalization
mySection->Law(1)->GetDomain(FirstS, Last);
DeltaS = Last - FirstS;
myLocation->CurvilinearBounds(NbL, First, Length);
Delta = Length;
if (N > 1)
{
Delta /= (N - 1);
}
myLocation->CurvilinearBounds(1, First, Last); // Initiation of Last
for (U = 0.0, ii = 1; !Finis; U += Delta)
{
if (U >= Length)
{
U = Length;
Finis = true;
}
else
{
if (ii < NbL)
{
myLocation->CurvilinearBounds(NbL, First, Last);
}
if (U > Last)
{
U = (Last + First) / 2; // The edge is not skipped
}
if (U > First)
{
ii++;
}
}
US = FirstS + (U / Length) * DeltaS;
// Calcul d'une section
mySection->D0(US, W);
myLocation->D0(U, W);
List.Append(W);
}
}
//=======================================================================
// function : Build
// purpose : Construct the Shell and the history
//=======================================================================
bool BRepFill_PipeShell::Build()
{
bool Ok;
double FirstS, LastS;
// 1) Preparation
Prepare();
if (myStatus != GeomFill_PipeOk)
{
BRep_Builder B;
TopoDS_Shell Sh;
B.MakeShell(Sh);
myShape = Sh; // Nullify
return false;
}
// 2) Calculate myFirst and myLast
mySection->Law(1)->GetDomain(FirstS, LastS);
mySection->D0(FirstS, myFirst);
myLocation->D0(0, myFirst);
if (mySection->IsVClosed() && myLocation->IsClosed())
{
if (myLocation->IsG1(0) >= 0)
{
myLast = myFirst;
}
else
{
myFirst.Nullify();
myLast.Nullify();
}
}
else
{
double Length;
myLocation->CurvilinearBounds(myLocation->NbLaw(), FirstS, Length);
mySection->D0(LastS, myLast);
myLocation->D0(Length, myLast);
// eap 5 Jun 2002 occ332, myLast and myFirst must not share one TShape,
// tolerances of shapes built on them may be quite different
if (myFirst.IsPartner(myLast))
{
BRepBuilderAPI_Copy copy(myLast);
if (copy.IsDone())
{
myLast = copy.Shape();
}
}
// eap 5 Jun 2002 occ332, end modif
}
// 3) Construction
BRepFill_Sweep MkSw(mySection, myLocation, true);
MkSw.SetTolerance(myTol3d, myBoundTol, 1.e-5, myTolAngular);
MkSw.SetAngularControl(angmin, angmax);
MkSw.SetForceApproxC1(myForceApproxC1);
MkSw.SetBounds(TopoDS::Wire(myFirst), TopoDS::Wire(myLast));
GeomAbs_Shape theContinuity = GeomAbs_C2;
if (myTrihedron == GeomFill_IsDiscreteTrihedron)
{
theContinuity = GeomAbs_C0;
}
NCollection_Map<TopoDS_Shape, TopTools_ShapeMapHasher> Dummy;
NCollection_DataMap<TopoDS_Shape,
occ::handle<NCollection_HArray2<TopoDS_Shape>>,
TopTools_ShapeMapHasher>
Dummy2;
NCollection_DataMap<TopoDS_Shape,
occ::handle<NCollection_HArray2<TopoDS_Shape>>,
TopTools_ShapeMapHasher>
Dummy3;
MkSw.Build(Dummy,
Dummy2,
Dummy3,
myTransition,
theContinuity,
GeomFill_Location,
myMaxDegree,
myMaxSegments);
myStatus = myLocation->GetStatus();
Ok = (MkSw.IsDone() && (myStatus == GeomFill_PipeOk));
if (Ok)
{
myShape = MkSw.Shape();
myErrorOnSurf = MkSw.ErrorOnSurface();
TopoDS_Shape aBottomWire = myFirst;
TopoDS_Shape aTopWire = myLast;
if (BuildBoundaries(MkSw, mySection, aBottomWire, aTopWire))
{
myFirst = aBottomWire;
myLast = aTopWire;
}
if (mySection->IsUClosed())
{
TopExp_Explorer explo;
bool DegenFirst = true, DegenLast = true;
for (explo.Init(myFirst, TopAbs_EDGE); explo.More(); explo.Next())
{
const TopoDS_Edge& anEdge = TopoDS::Edge(explo.Current());
DegenFirst = DegenFirst && BRep_Tool::Degenerated(anEdge);
}
for (explo.Init(myLast, TopAbs_EDGE); explo.More(); explo.Next())
{
const TopoDS_Edge& anEdge = TopoDS::Edge(explo.Current());
DegenLast = DegenLast && BRep_Tool::Degenerated(anEdge);
}
if (DegenFirst && DegenLast)
{
myShape.Closed(true);
}
}
if (myIsBuildHistory)
{
BuildHistory(MkSw);
}
}
else
{
BRep_Builder B;
TopoDS_Shell Sh;
B.MakeShell(Sh);
myShape = Sh; // Nullify
if (myStatus == GeomFill_PipeOk)
{
myStatus = GeomFill_PipeNotOk;
}
}
return Ok;
}
//=================================================================================================
bool BRepFill_PipeShell::MakeSolid()
{
if (myShape.IsNull())
{
throw StdFail_NotDone("PipeShell is not built");
}
bool B = myShape.Closed();
BRep_Builder BS;
if (!B)
{
if (!myFirst.IsNull() && !myLast.IsNull())
{
B = (myFirst.Closed() && myLast.Closed());
}
if (B)
{
// It is necessary to block the extremities
B = PerformPlan(myFirst);
if (B)
{
B = PerformPlan(myLast);
if (B)
{
if (!myFirst.IsNull() && !IsSameOriented(myFirst, myShape))
{
myFirst.Reverse();
}
if (!myLast.IsNull() && !IsSameOriented(myLast, myShape))
{
myLast.Reverse();
}
if (!myFirst.IsNull())
{
BS.Add(myShape, TopoDS::Face(myFirst));
}
if (!myLast.IsNull())
{
BS.Add(myShape, TopoDS::Face(myLast));
}
myShape.Closed(true);
}
}
}
}
if (B)
{
TopoDS_Solid solid;
BS.MakeSolid(solid);
BS.Add(solid, TopoDS::Shell(myShape));
BRepClass3d_SolidClassifier SC(solid);
SC.PerformInfinitePoint(Precision::Confusion());
if (SC.State() == TopAbs_IN)
{
BS.MakeSolid(solid);
myShape.Reverse();
BS.Add(solid, TopoDS::Shell(myShape));
}
myShape = solid;
myShape.Closed(true);
}
return B;
}
//=================================================================================================
const TopoDS_Shape& BRepFill_PipeShell::Shape() const
{
return myShape;
}
//=================================================================================================
double BRepFill_PipeShell::ErrorOnSurface() const
{
return myErrorOnSurf;
}
//=================================================================================================
const TopoDS_Shape& BRepFill_PipeShell::FirstShape() const
{
return myFirst;
}
//=================================================================================================
const TopoDS_Shape& BRepFill_PipeShell::LastShape() const
{
return myLast;
}
//=================================================================================================
void BRepFill_PipeShell::Generated(const TopoDS_Shape& theShape,
NCollection_List<TopoDS_Shape>& theList)
{
theList.Clear();
if (myGenMap.IsBound(theShape))
{
theList = myGenMap.Find(theShape);
}
}
//=======================================================================
// function : Prepare
// purpose : - Check that everything is ready
// - Construct the law of section
// - Construct the law of location if required
// - Calculate First & Last
//=======================================================================
void BRepFill_PipeShell::Prepare()
{
WSeq.Clear();
myEdgeNewEdges.Clear();
TopoDS_Wire theSect;
if (!IsReady())
{
throw StdFail_NotDone("PipeShell");
}
if (!myLocation.IsNull() && !mySection.IsNull())
{
return; // It is ready
}
// Check set of section for right configuration of punctual sections
int i;
TopoDS_Iterator iter;
for (i = 2; i <= mySeq.Length() - 1; i++)
{
bool wdeg = true;
for (iter.Initialize(mySeq(i).Wire()); iter.More(); iter.Next())
{
const TopoDS_Edge& anEdge = TopoDS::Edge(iter.Value());
wdeg = wdeg && (BRep_Tool::Degenerated(anEdge));
}
if (wdeg)
{
throw Standard_Failure("Wrong usage of punctual sections");
}
}
if (mySeq.Length() <= 2)
{
bool wdeg = true;
for (i = 1; i <= mySeq.Length(); i++)
{
for (iter.Initialize(mySeq(i).Wire()); iter.More(); iter.Next())
{
const TopoDS_Edge& anEdge = TopoDS::Edge(iter.Value());
wdeg = wdeg && (BRep_Tool::Degenerated(anEdge));
}
}
if (wdeg)
{
throw Standard_Failure("Wrong usage of punctual sections");
}
}
// Construction of the law of location
if (myLocation.IsNull())
{
switch (myTrihedron)
{
case GeomFill_IsCorrectedFrenet: {
occ::handle<GeomFill_TrihedronLaw> TLaw = new (GeomFill_CorrectedFrenet)();
occ::handle<GeomFill_CurveAndTrihedron> Loc = new (GeomFill_CurveAndTrihedron)(TLaw);
myLocation = new (BRepFill_Edge3DLaw)(mySpine, Loc);
break;
}
default: { // Not planned!
throw Standard_ConstructionError("PipeShell");
}
}
}
// Transformation of the law (Transition Management)
PerformTransition(myTransition, myLocation, angmin);
// Construction of the section law
if (mySeq.Length() == 1)
{
double p1;
gp_Trsf aTrsf;
Place(mySeq(1), theSect, aTrsf, p1);
TopoDS_Wire aLocalShape = theSect;
if (mySeq(1).IsLaw())
{
mySection = new BRepFill_ShapeLaw(aLocalShape, myLaw);
// mySection = new (BRepFill_ShapeLaw) (TopoDS_Wire(theSect), myLaw);
}
else
{
mySection = new BRepFill_ShapeLaw(aLocalShape);
}
// mySection = new (BRepFill_ShapeLaw) (TopoDS::Wire(theSect));
WSeq.Append(theSect);
// Simple case of single section
myIndOfSec.Append(1);
TopoDS_Iterator itw(theSect);
for (; itw.More(); itw.Next())
{
const TopoDS_Shape& anEdge = itw.Value();
NCollection_List<TopoDS_Shape> Elist;
Elist.Append(anEdge);
myEdgeNewEdges.Bind(anEdge, Elist);
}
///////////////////////////////
}
else
{
NCollection_Sequence<double> Param;
NCollection_Sequence<int> IndSec;
NCollection_Sequence<gp_Trsf> Transformations;
int NbL = myLocation->NbLaw();
gp_Trsf aTrsf;
double V1, V2, param;
myLocation->CurvilinearBounds(NbL, V1, V2);
V1 = 0.;
int ideb = 0, ifin = 0;
int iseq;
for (iseq = 1; iseq <= mySeq.Length(); iseq++)
{
IndSec.Append(iseq);
Place(mySeq(iseq), theSect, aTrsf, param);
Param.Append(param);
WSeq.Append(theSect);
Transformations.Append(aTrsf);
if (param == V1)
{
ideb = iseq;
}
if (param == V2)
{
ifin = iseq;
}
}
// looping sections ?
if (myLocation->IsClosed())
{
if (ideb > 0)
{
// place the initial section at the final position
Param.Append(V2);
WSeq.Append(WSeq(ideb));
}
else if (ifin > 0)
{
// place the final section at the initial position
Param.Append(V1);
WSeq.Append(WSeq(ifin));
}
else
{
// it is necessary to find a medium section to impose by V1 and by V2
double pmin = RealLast(), pmax = RealFirst();
TopoDS_Wire Wmin, Wmax;
for (iseq = 1; iseq <= WSeq.Length(); iseq++)
{
if (Param.Value(iseq) < pmin)
{
pmin = Param.Value(iseq);
Wmin = TopoDS::Wire(WSeq.Value(iseq));
}
if (Param.Value(iseq) > pmax)
{
pmax = Param.Value(iseq);
Wmax = TopoDS::Wire(WSeq.Value(iseq));
}
}
// medium section between Wmin and Wmax
TopoDS_Wire Wres;
double dmin = std::abs(pmin - V1);
double dmax = std::abs(pmax - V2);
if (ComputeSection(Wmin, Wmax, dmin, dmax, Wres))
{
// impose section Wres at the beginning and the end
Param.Append(V1);
WSeq.Append(Wres);
IndSec.Append(WSeq.Length());
Param.Append(V2);
WSeq.Append(Wres);
IndSec.Append(WSeq.Length());
}
}
}
// parse sections by increasing parameter
bool play_again = true;
while (play_again)
{
play_again = false;
for (iseq = 1; iseq <= WSeq.Length(); iseq++)
{
for (int jseq = iseq + 1; jseq <= WSeq.Length(); jseq++)
{
if (Param.Value(iseq) > Param.Value(jseq))
{
Param.Exchange(iseq, jseq);
WSeq.Exchange(iseq, jseq);
IndSec.Exchange(iseq, jseq);
play_again = true;
}
}
}
}
// Fill the array of real indices of sections
for (int ii = 1; ii <= mySeq.Length(); ii++)
{
for (int jj = 1; jj <= IndSec.Length(); jj++)
{
if (IndSec(jj) == ii)
{
myIndOfSec.Append(jj);
break;
}
}
}
// Calculate work sections
NCollection_Sequence<TopoDS_Shape> WorkingSections;
WorkingSections.Clear();
NCollection_DataMap<TopoDS_Shape, NCollection_List<TopoDS_Shape>, TopTools_ShapeMapHasher>
WorkingMap;
BRepFill_CompatibleWires Georges(WSeq);
Georges.SetPercent(0.1);
Georges.Perform(false);
if (Georges.IsDone())
{
WorkingSections = Georges.Shape();
WorkingMap = Georges.Generated();
// For each sub-edge of each section
// we save its splits
for (int ii = 1; ii <= WSeq.Length(); ii++)
{
TopExp_Explorer Explo(WSeq(ii), TopAbs_EDGE);
for (; Explo.More(); Explo.Next())
{
const TopoDS_Edge& anEdge = TopoDS::Edge(Explo.Current());
const NCollection_List<TopoDS_Shape>& aNewEdges = Georges.GeneratedShapes(anEdge);
myEdgeNewEdges.Bind(anEdge, aNewEdges);
}
}
}
else
{
throw Standard_ConstructionError("PipeShell : uncompatible wires");
}
mySection = new (BRepFill_NSections)(WorkingSections, Transformations, Param, V1, V2);
} // else
// modify the law of location if contact
if ((myTrihedron == GeomFill_IsGuidePlanWithContact)
|| (myTrihedron == GeomFill_IsGuideACWithContact))
{
double fs, f, l, Delta, Length;
occ::handle<GeomFill_LocationGuide> Loc;
occ::handle<GeomFill_SectionLaw> Sec = mySection->ConcatenedLaw();
myLocation->CurvilinearBounds(myLocation->NbLaw(), f, Length);
Sec->GetDomain(fs, l);
Delta = (l - fs) / Length;
double angle, old_angle = 0;
for (int ipath = 1; ipath <= myLocation->NbLaw(); ipath++)
{
myLocation->CurvilinearBounds(ipath, f, l);
Loc = occ::down_cast<GeomFill_LocationGuide>(myLocation->Law(ipath));
Loc->Set(Sec, true, fs + f * Delta, fs + l * Delta, old_angle,
angle); // force the rotation
old_angle = angle;
}
}
myStatus = myLocation->GetStatus();
if (!mySection->IsDone())
{
myStatus = GeomFill_PipeNotOk;
}
}
//=======================================================================
// function : Place
// purpose : Implement a Section in the local reference frame
// and return its parameter on the trajectory
//=======================================================================
void BRepFill_PipeShell::Place(const BRepFill_Section& Sec,
TopoDS_Wire& W,
gp_Trsf& aTrsf,
double& param)
{
BRepFill_SectionPlacement Place(myLocation,
Sec.Wire(),
Sec.Vertex(),
Sec.WithContact(),
Sec.WithCorrection());
const TopoDS_Wire& TmpWire = Sec.Wire();
aTrsf = Place.Transformation();
// Transform the copy
W = TopoDS::Wire(BRepBuilderAPI_Transform(TmpWire, aTrsf, true));
////////////////////////////////////
param = Place.AbscissaOnPath();
}
//=======================================================================
// function : ResetLoc
// purpose : Remove references to the sections in the laws of location
//=======================================================================
void BRepFill_PipeShell::ResetLoc()
{
if ((myTrihedron == GeomFill_IsGuidePlanWithContact)
|| (myTrihedron == GeomFill_IsGuideACWithContact))
{
occ::handle<GeomFill_LocationGuide> Loc;
for (int isec = 1; isec <= myLocation->NbLaw(); isec++)
{
Loc = occ::down_cast<GeomFill_LocationGuide>(myLocation->Law(isec));
Loc->EraseRotation(); // remove the rotation
}
}
}
//=======================================================================
// function : BuildHistory
// purpose : Builds history for edges and vertices of sections,
// for edges and vertices of spine
//=======================================================================
void BRepFill_PipeShell::BuildHistory(const BRepFill_Sweep& theSweep)
{
// Filling of <myGenMap>
const occ::handle<NCollection_HArray2<TopoDS_Shape>>& anUEdges = theSweep.InterFaces();
BRep_Builder BB;
NCollection_DataMap<int, TopoDS_Shape> IndWireMap;
int indw, inde;
TopoDS_Iterator itw;
for (indw = 1; indw <= mySeq.Length(); indw++)
{
const TopoDS_Shape& Section = mySeq(indw).OriginalShape();
TopoDS_Wire aSection;
bool IsPunctual = mySeq(indw).IsPunctual();
if (IsPunctual)
{
// for punctual sections (first or last)
// we take all the wires generated along the path
NCollection_List<TopoDS_Shape>* Elist =
myGenMap.Bound(Section, NCollection_List<TopoDS_Shape>());
for (int i = 1; i <= anUEdges->UpperRow(); i++)
{
for (int j = 1; j <= anUEdges->UpperCol(); j++)
{
Elist->Append(anUEdges->Value(i, j));
}
}
continue;
}
else
{
aSection = TopoDS::Wire(Section);
}
// Take the real index of section on the path
int IndOfW = myIndOfSec(indw);
const TopoDS_Wire& theWire = TopoDS::Wire(WSeq(IndOfW));
BRepTools_WireExplorer wexp_sec(aSection);
for (inde = 1; wexp_sec.More(); wexp_sec.Next())
{
const TopoDS_Edge& anOriginalEdge = TopoDS::Edge(wexp_sec.Current());
TopoDS_Edge anEdge = TopoDS::Edge(mySeq(indw).ModifiedShape(anOriginalEdge));
if (BRep_Tool::Degenerated(anEdge))
{
continue;
}
TopoDS_Shell aShell;
BB.MakeShell(aShell);
TopoDS_Vertex aVertex[2];
TopExp::Vertices(anOriginalEdge, aVertex[0], aVertex[1]);
int SignOfAnEdge = (anOriginalEdge.Orientation() == TopAbs_FORWARD) ? 1 : -1;
// For each non-degenerated inde-th edge of <aSection>
// we find inde-th edge in <theWire>
TopoDS_Edge theEdge;
BRepTools_WireExplorer wexp(theWire);
for (int i = 1; wexp.More(); wexp.Next())
{
theEdge = TopoDS::Edge(wexp.Current());
if (BRep_Tool::Degenerated(anEdge))
{
continue;
}
if (i == inde)
{
break;
}
i++;
}
// Take the list of splits for <theEdge>
const NCollection_List<TopoDS_Shape>& NewEdges = myEdgeNewEdges(theEdge);
int SignOfANewEdge = 0, SignOfIndex = 0;
NCollection_List<TopoDS_Shape>::Iterator iter(NewEdges);
for (; iter.More(); iter.Next())
{
const TopoDS_Edge& aNewEdge = TopoDS::Edge(iter.Value());
SignOfANewEdge = (aNewEdge.Orientation() == TopAbs_FORWARD) ? 1 : -1;
int anIndE = mySection->IndexOfEdge(aNewEdge);
SignOfIndex = (anIndE > 0) ? 1 : -1;
anIndE = std::abs(anIndE);
// For an edge generated shape is a "tape" -
// a shell usually containing this edge and
// passing from beginning of path to its end
TopoDS_Shape aTape = theSweep.Tape(anIndE);
TopoDS_Iterator itsh(aTape);
for (; itsh.More(); itsh.Next())
{
BB.Add(aShell, itsh.Value());
}
}
// Processing of vertices of <anEdge>
// We should choose right index in <anUEdges>
// for each vertex of edge
int ToReverse = SignOfAnEdge * SignOfANewEdge * SignOfIndex;
int UIndex[2];
UIndex[0] = std::abs(mySection->IndexOfEdge(NewEdges.First()));
UIndex[1] = std::abs(mySection->IndexOfEdge(NewEdges.Last())) + ToReverse;
if (ToReverse == -1)
{
UIndex[0]++;
UIndex[1]++;
}
if (mySection->IsUClosed())
{
if (UIndex[0] > mySection->NbLaw())
{
UIndex[0] = 1;
}
if (UIndex[1] > mySection->NbLaw())
{
UIndex[1] = 1;
}
}
// if (SignOfAnEdge * SignOfANewEdge == -1)
if (SignOfAnEdge == -1 || SignOfANewEdge == -1)
{
int Tmp = UIndex[0];
UIndex[0] = UIndex[1];
UIndex[1] = Tmp;
}
NCollection_IndexedDataMap<TopoDS_Shape,
NCollection_List<TopoDS_Shape>,
TopTools_ShapeMapHasher>
VEmap;
TopExp::MapShapesAndAncestors(aShell, TopAbs_VERTEX, TopAbs_EDGE, VEmap);
for (int kk = 0; kk < 2; kk++)
{
if (myGenMap.IsBound(aVertex[kk]))
{
continue;
}
if (IndWireMap.IsBound(UIndex[kk]))
{
NCollection_List<TopoDS_Shape>* Elist =
myGenMap.Bound(aVertex[kk], NCollection_List<TopoDS_Shape>());
for (itw.Initialize(IndWireMap(UIndex[kk])); itw.More(); itw.Next())
{
Elist->Append(itw.Value());
}
continue;
}
// Collect u-edges
NCollection_Sequence<TopoDS_Shape> SeqEdges;
int jj;
for (jj = 1; jj <= anUEdges->UpperCol(); jj++)
{
SeqEdges.Append(anUEdges->Value(UIndex[kk], jj));
}
// Assemble the wire ("rail" along the path)
// checking for possible holes
//(they appear with option "Round Corner")
// and filling them
// Missed edges are taken from <aShell>
TopoDS_Wire aWire;
BB.MakeWire(aWire);
const TopoDS_Edge& FirstEdge = TopoDS::Edge(SeqEdges(1));
if (FirstEdge.IsNull())
{
continue;
}
BB.Add(aWire, FirstEdge);
TopoDS_Vertex FirstVertex, CurVertex;
TopExp::Vertices(FirstEdge, FirstVertex, CurVertex);
TopoDS_Edge CurEdge;
for (jj = 2; jj <= SeqEdges.Length(); jj++)
{
CurEdge = TopoDS::Edge(SeqEdges(jj));
TopoDS_Vertex Vfirst, Vlast;
TopExp::Vertices(CurEdge, Vfirst, Vlast);
if (CurVertex.IsSame(Vfirst))
{
CurVertex = Vlast;
}
else // a hole
{
const NCollection_List<TopoDS_Shape>& Elist = VEmap.FindFromKey(Vfirst);
NCollection_List<TopoDS_Shape>::Iterator itl(Elist);
for (; itl.More(); itl.Next())
{
const TopoDS_Edge& Candidate = TopoDS::Edge(itl.Value());
if (Candidate.IsSame(CurEdge))
{
continue;
}
TopoDS_Vertex V1, V2;
TopExp::Vertices(Candidate, V1, V2);
if (V1.IsSame(CurVertex) || V2.IsSame(CurVertex))
{
BB.Add(aWire, Candidate);
break;
}
}
}
CurVertex = Vlast;
BB.Add(aWire, CurEdge);
} // for (jj = 2; jj <= SeqEdges.Length(); jj++)
// case of closed wire
if (myLocation->IsClosed() && !CurVertex.IsSame(FirstVertex))
{
const NCollection_List<TopoDS_Shape>& Elist = VEmap.FindFromKey(CurVertex);
NCollection_List<TopoDS_Shape>::Iterator itl(Elist);
for (; itl.More(); itl.Next())
{
const TopoDS_Edge& Candidate = TopoDS::Edge(itl.Value());
if (Candidate.IsSame(CurEdge))
{
continue;
}
TopoDS_Vertex V1, V2;
TopExp::Vertices(Candidate, V1, V2);
if (V1.IsSame(FirstVertex) || V2.IsSame(FirstVertex))
{
BB.Add(aWire, Candidate);
break;
}
}
}
NCollection_List<TopoDS_Shape>* Elist =
myGenMap.Bound(aVertex[kk], NCollection_List<TopoDS_Shape>());
for (itw.Initialize(aWire); itw.More(); itw.Next())
{
Elist->Append(itw.Value());
}
// Save already built wire with its index
IndWireMap.Bind(UIndex[kk], aWire);
} // for (int kk = 0; kk < 2; kk++)
////////////////////////////////////
NCollection_List<TopoDS_Shape>* Flist =
myGenMap.Bound(anOriginalEdge, NCollection_List<TopoDS_Shape>());
TopoDS_Iterator itsh(aShell);
for (; itsh.More(); itsh.Next())
{
Flist->Append(itsh.Value());
}
////////////////////////
inde++;
}
}
// For subshapes of spine
const occ::handle<NCollection_HArray2<TopoDS_Shape>>& aFaces = theSweep.SubShape();
const occ::handle<NCollection_HArray2<TopoDS_Shape>>& aVEdges = theSweep.Sections();
BRepTools_WireExplorer wexp(mySpine);
inde = 0;
bool ToExit = false;
for (;;)
{
if (!wexp.More())
{
ToExit = true;
}
inde++;
if (!ToExit)
{
const TopoDS_Edge& anEdgeOfSpine = wexp.Current();
NCollection_List<TopoDS_Shape>* Flist =
myGenMap.Bound(anEdgeOfSpine, NCollection_List<TopoDS_Shape>());
for (int i = 1; i <= aFaces->UpperRow(); i++)
{
const TopoDS_Shape& aFace = aFaces->Value(i, inde);
if (aFace.ShapeType() == TopAbs_FACE)
{
Flist->Append(aFace);
}
}
}
const TopoDS_Vertex& aVertexOfSpine = wexp.CurrentVertex();
NCollection_List<TopoDS_Shape>* ListVshapes =
myGenMap.Bound(aVertexOfSpine, NCollection_List<TopoDS_Shape>());
for (int i = 1; i <= aVEdges->UpperRow(); i++)
{
const TopoDS_Shape& aVshape = aVEdges->Value(i, inde);
if (aVshape.IsNull())
{
continue;
}
if (aVshape.ShapeType() == TopAbs_EDGE || aVshape.ShapeType() == TopAbs_FACE)
{
ListVshapes->Append(aVshape);
}
else
{
TopoDS_Iterator itvshape(aVshape);
for (; itvshape.More(); itvshape.Next())
{
const TopoDS_Shape& aSubshape = itvshape.Value();
if (aSubshape.ShapeType() == TopAbs_EDGE || aSubshape.ShapeType() == TopAbs_FACE)
{
ListVshapes->Append(aSubshape);
}
else
{
// it is wire
for (itw.Initialize(aSubshape); itw.More(); itw.Next())
{
ListVshapes->Append(itw.Value());
}
}
}
}
}
if (ToExit)
{
break;
}
if (wexp.More())
{
wexp.Next();
}
}
}
//=================================================================================================
bool BuildBoundaries(const BRepFill_Sweep& theSweep,
const occ::handle<BRepFill_SectionLaw>& theSection,
TopoDS_Shape& theBottom,
TopoDS_Shape& theTop)
{
TopoDS_Wire aBottomWire;
TopoDS_Wire aTopWire;
BRep_Builder aB;
aB.MakeWire(aBottomWire);
aB.MakeWire(aTopWire);
bool bfoundbottom = false;
bool bfoundtop = false;
occ::handle<NCollection_HArray2<TopoDS_Shape>> aVEdges = theSweep.Sections();
int i = 0;
bool bAllSame = true;
for (i = 1; i <= theSection->NbLaw(); i++)
{
const TopoDS_Shape& aBottomEdge = aVEdges->Value(i, aVEdges->LowerCol());
if (!aBottomEdge.IsNull() && (aBottomEdge.ShapeType() == TopAbs_EDGE))
{
aB.Add(aBottomWire, aBottomEdge);
bfoundbottom = true;
}
const TopoDS_Shape& aTopEdge = aVEdges->Value(i, aVEdges->UpperCol());
if (!aTopEdge.IsNull() && (aTopEdge.ShapeType() == TopAbs_EDGE))
{
aB.Add(aTopWire, aTopEdge);
bfoundtop = true;
}
if (!aBottomEdge.IsNull() && !aTopEdge.IsNull() && !aBottomEdge.IsSame(aTopEdge))
{
bAllSame = false;
}
}
if (theSection->IsUClosed())
{
aBottomWire.Closed(true);
aTopWire.Closed(true);
}
if (bfoundbottom)
{
theBottom = aBottomWire;
}
if (bfoundtop)
{
theTop = aTopWire;
}
if (bAllSame && bfoundbottom && bfoundtop)
{
theTop = theBottom;
}
return bfoundbottom || bfoundtop;
}