Loading files
3d097a032This file is pinned to the selected release. Download the original to open it in your design tool.
// Created on: 1993-11-18
// Created by: Isabelle GRIGNON
// Copyright (c) 1993-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 <Adaptor2d_Curve2d.hxx>
#include <Blend_FuncInv.hxx>
#include <BRepBlend_Line.hxx>
#include <BRepLib.hxx>
#include <BRepTopAdaptor_TopolTool.hxx>
#include <ChFi3d_Builder.hxx>
#include <ChFi3d_Builder_0.hxx>
#include <ChFiDS_CommonPoint.hxx>
#include <ChFiDS_SurfData.hxx>
#include <NCollection_Sequence.hxx>
#include <NCollection_HSequence.hxx>
#include <ChFiDS_Stripe.hxx>
#include <NCollection_List.hxx>
#include <ChFiDS_Spine.hxx>
#include <Geom2d_Curve.hxx>
#include <gp_Pnt2d.hxx>
#include <Precision.hxx>
#include <ShapeFix.hxx>
#include <Standard_ErrorHandler.hxx>
#include <Standard_Failure.hxx>
#include <Standard_NotImplemented.hxx>
#include <Standard_Integer.hxx>
#include <NCollection_Map.hxx>
#include <TopAbs_ShapeEnum.hxx>
#include <TopExp_Explorer.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Edge.hxx>
#include <TopoDS_Face.hxx>
#include <TopoDS_Shape.hxx>
#include <TopoDS_Vertex.hxx>
#include <TopOpeBRepBuild_HBuilder.hxx>
#include <TopOpeBRepDS_Curve.hxx>
#include <TopOpeBRepDS_CurveExplorer.hxx>
#include <TopOpeBRepDS_CurvePointInterference.hxx>
#include <TopOpeBRepDS_DataStructure.hxx>
#include <TopOpeBRepDS_HDataStructure.hxx>
#include <TopOpeBRepDS_Interference.hxx>
#include <TopOpeBRepDS_PointIterator.hxx>
//=================================================================================================
static void CompleteDS(TopOpeBRepDS_DataStructure& DStr, const TopoDS_Shape& S)
{
ChFiDS_Map MapEW, MapFS;
MapEW.Fill(S, TopAbs_EDGE, TopAbs_WIRE);
MapFS.Fill(S, TopAbs_FACE, TopAbs_SHELL);
TopExp_Explorer ExpE;
for (ExpE.Init(S, TopAbs_EDGE); ExpE.More(); ExpE.Next())
{
const TopoDS_Edge& E = TopoDS::Edge(ExpE.Current());
bool hasgeom = DStr.HasGeometry(E);
if (hasgeom)
{
const NCollection_List<TopoDS_Shape>& WireListAnc = MapEW(E);
NCollection_List<TopoDS_Shape>::Iterator itaW(WireListAnc);
while (itaW.More())
{
const TopoDS_Shape& WireAnc = itaW.Value();
DStr.AddShape(WireAnc);
itaW.Next();
}
}
}
TopExp_Explorer ExpF;
for (ExpF.Init(S, TopAbs_FACE); ExpF.More(); ExpF.Next())
{
const TopoDS_Face& F = TopoDS::Face(ExpF.Current());
bool hasgeom = DStr.HasGeometry(F);
if (hasgeom)
{
const NCollection_List<TopoDS_Shape>& ShellListAnc = MapFS(F);
NCollection_List<TopoDS_Shape>::Iterator itaS(ShellListAnc);
while (itaS.More())
{
const TopoDS_Shape& ShellAnc = itaS.Value();
DStr.AddShape(ShellAnc);
itaS.Next();
}
}
}
// set the range on the DS Curves
for (int ic = 1; ic <= DStr.NbCurves(); ic++)
{
const NCollection_List<occ::handle<TopOpeBRepDS_Interference>>& LI =
DStr.CurveInterferences(ic);
TopOpeBRepDS_PointIterator it(LI);
if (!it.More())
{
continue;
}
double parmin = it.Parameter(), parmax = parmin;
for (it.Next(); it.More(); it.Next())
{
double par = it.Parameter();
parmin = std::min(parmin, par);
parmax = std::max(parmax, par);
}
DStr.ChangeCurve(ic).SetRange(parmin, parmax);
}
}
//=================================================================================================
ChFi3d_Builder::~ChFi3d_Builder() = default;
//=================================================================================================
void ChFi3d_Builder::ExtentAnalyse()
{
int nbedges, nbs;
for (int iv = 1; iv <= myVDataMap.Extent(); iv++)
{
nbs = myVDataMap(iv).Extent();
const TopoDS_Vertex& Vtx = myVDataMap.FindKey(iv);
// nbedges = ChFi3d_NumberOfEdges(Vtx, myVEMap);
nbedges = ChFi3d_NumberOfSharpEdges(Vtx, myVEMap, myEFMap);
switch (nbs)
{
case 1:
ExtentOneCorner(Vtx, myVDataMap.FindFromIndex(iv).First());
break;
case 2:
if (nbedges <= 3)
{
ExtentTwoCorner(Vtx, myVDataMap.FindFromIndex(iv));
}
break;
case 3:
if (nbedges <= 3)
{
ExtentThreeCorner(Vtx, myVDataMap.FindFromIndex(iv));
}
break;
default:
break;
}
}
}
//=================================================================================================
void ChFi3d_Builder::Compute()
{
UpdateTolesp();
if (myListStripe.IsEmpty())
{
throw Standard_Failure("There are no suitable edges for chamfer or fillet");
}
Reset();
myDS = new TopOpeBRepDS_HDataStructure();
TopOpeBRepDS_DataStructure& DStr = myDS->ChangeDS();
done = true;
hasresult = false;
// filling of myVDatatMap
NCollection_List<occ::handle<ChFiDS_Stripe>>::Iterator itel;
for (itel.Initialize(myListStripe); itel.More(); itel.Next())
{
if ((itel.Value()->Spine()->FirstStatus() <= ChFiDS_BreakPoint))
{
myVDataMap.Add(itel.Value()->Spine()->FirstVertex(), itel.Value());
}
else if (itel.Value()->Spine()->FirstStatus() == ChFiDS_FreeBoundary)
{
ExtentOneCorner(itel.Value()->Spine()->FirstVertex(), itel.Value());
}
if ((itel.Value()->Spine()->LastStatus() <= ChFiDS_BreakPoint))
{
myVDataMap.Add(itel.Value()->Spine()->LastVertex(), itel.Value());
}
else if (itel.Value()->Spine()->LastStatus() == ChFiDS_FreeBoundary)
{
ExtentOneCorner(itel.Value()->Spine()->LastVertex(), itel.Value());
}
}
// preanalysis to evaluate the extensions.
ExtentAnalyse();
// Construction of the stripe of fillet on each stripe.
for (itel.Initialize(myListStripe); itel.More(); itel.Next())
{
itel.Value()->Spine()->SetErrorStatus(ChFiDS_Ok);
try
{
OCC_CATCH_SIGNALS
PerformSetOfSurf(itel.ChangeValue());
}
catch (Standard_Failure const& anException)
{
#ifdef OCCT_DEBUG
std::cout << "EXCEPTION Stripe compute " << anException << std::endl;
#endif
(void)anException;
badstripes.Append(itel.Value());
done = true;
if (itel.Value()->Spine()->ErrorStatus() == ChFiDS_Ok)
{
itel.Value()->Spine()->SetErrorStatus(ChFiDS_Error);
}
}
if (!done)
{
badstripes.Append(itel.Value());
}
done = true;
}
done = (badstripes.IsEmpty());
// construct fillets on each vertex + feed the Ds
if (done)
{
int j;
for (j = 1; j <= myVDataMap.Extent(); j++)
{
try
{
OCC_CATCH_SIGNALS
PerformFilletOnVertex(j);
}
catch (Standard_Failure const& anException)
{
#ifdef OCCT_DEBUG
std::cout << "EXCEPTION Corner compute " << anException << std::endl;
#endif
(void)anException;
badvertices.Append(myVDataMap.FindKey(j));
hasresult = false;
done = true;
}
if (!done)
{
badvertices.Append(myVDataMap.FindKey(j));
}
done = true;
}
if (!hasresult)
{
done = badvertices.IsEmpty();
}
}
NCollection_Map<int> MapIndSo;
TopExp_Explorer expso(myShape, TopAbs_SOLID);
for (; expso.More(); expso.Next())
{
const TopoDS_Shape& cursol = expso.Current();
int indcursol = DStr.AddShape(cursol);
MapIndSo.Add(indcursol);
}
TopExp_Explorer expsh(myShape, TopAbs_SHELL, TopAbs_SOLID);
for (; expsh.More(); expsh.Next())
{
const TopoDS_Shape& cursh = expsh.Current();
int indcursh = DStr.AddShape(cursh);
MapIndSo.Add(indcursh);
}
if (done)
{
int i1;
for (itel.Initialize(myListStripe), i1 = 0; itel.More(); itel.Next(), i1++)
{
const occ::handle<ChFiDS_Stripe>& st = itel.Value();
// 05/02/02 akm vvv : (OCC119) First we'll check ain't there
// intersections between fillets
NCollection_List<occ::handle<ChFiDS_Stripe>>::Iterator itel1;
int i2;
for (itel1.Initialize(myListStripe), i2 = 0; itel1.More(); itel1.Next(), i2++)
{
if (i2 <= i1)
{
// Do not twice intersect the stripes
continue;
}
occ::handle<ChFiDS_Stripe> aCheckStripe = itel1.Value();
try
{
OCC_CATCH_SIGNALS
ChFi3d_StripeEdgeInter(st, aCheckStripe, DStr, tol2d);
}
catch (Standard_Failure const& anException)
{
#ifdef OCCT_DEBUG
std::cout << "EXCEPTION Fillets compute " << anException << std::endl;
#endif
(void)anException;
badstripes.Append(itel.Value());
hasresult = false;
done = false;
break;
}
}
// 05/02/02 akm ^^^
int solidindex = st->SolidIndex();
ChFi3d_FilDS(solidindex, st, DStr, myRegul, tolapp3d, tol2d);
if (!done)
{
break;
}
}
if (done)
{
BRep_Builder B1;
CompleteDS(DStr, myShape);
// Update tolerances on vertex to max adjacent edges or
// Update tolerances on degenerated edge to max of adjacent vertexes.
TopOpeBRepDS_CurveExplorer cex(DStr);
for (; cex.More(); cex.Next())
{
TopOpeBRepDS_Curve& c = *((TopOpeBRepDS_Curve*)(void*)&(cex.Curve()));
double tolc = 0.;
bool degen = c.Curve().IsNull();
if (!degen)
{
tolc = c.Tolerance();
}
int ic = cex.Index();
TopOpeBRepDS_PointIterator It(myDS->CurvePoints(ic));
for (; It.More(); It.Next())
{
occ::handle<TopOpeBRepDS_CurvePointInterference> II;
II = occ::down_cast<TopOpeBRepDS_CurvePointInterference>(It.Value());
if (II.IsNull())
{
continue;
}
TopOpeBRepDS_Kind gk = II->GeometryType();
int gi = II->Geometry();
if (gk == TopOpeBRepDS_VERTEX)
{
const TopoDS_Vertex& v = TopoDS::Vertex(myDS->Shape(gi));
double tolv = BRep_Tool::Tolerance(v);
if (tolv > 0.0001)
{
tolv += 0.0003;
if (tolc < tolv)
{
tolc = tolv + 0.00001;
}
}
if (degen && tolc < tolv)
{
tolc = tolv;
}
else if (tolc > tolv)
{
B1.UpdateVertex(v, tolc);
}
}
else if (gk == TopOpeBRepDS_POINT)
{
TopOpeBRepDS_Point& p = DStr.ChangePoint(gi);
double tolp = p.Tolerance();
if (degen && tolc < tolp)
{
tolc = tolp;
}
else if (tolc > tolp)
{
p.Tolerance(tolc);
}
}
}
if (degen)
{
c.Tolerance(tolc);
}
}
myCoup->Perform(myDS);
NCollection_Map<int>::Iterator It(MapIndSo);
for (; It.More(); It.Next())
{
int indsol = It.Key();
const TopoDS_Shape& curshape = DStr.Shape(indsol);
myCoup->MergeSolid(curshape, TopAbs_IN);
}
int i = 1, n = DStr.NbShapes();
for (; i <= n; i++)
{
const TopoDS_Shape S = DStr.Shape(i);
if (S.ShapeType() != TopAbs_EDGE)
{
continue;
}
bool issplitIN = myCoup->IsSplit(S, TopAbs_IN);
if (!issplitIN)
{
continue;
}
NCollection_List<TopoDS_Shape>::Iterator it(myCoup->Splits(S, TopAbs_IN));
for (; it.More(); it.Next())
{
const TopoDS_Edge& newE = TopoDS::Edge(it.Value());
double tole = BRep_Tool::Tolerance(newE);
TopExp_Explorer exv(newE, TopAbs_VERTEX);
for (; exv.More(); exv.Next())
{
const TopoDS_Vertex& v = TopoDS::Vertex(exv.Current());
double tolv = BRep_Tool::Tolerance(v);
if (tole > tolv)
{
B1.UpdateVertex(v, tole);
}
}
}
}
if (!hasresult)
{
B1.MakeCompound(TopoDS::Compound(myShapeResult));
for (It = NCollection_Map<int>::Iterator(MapIndSo); It.More(); It.Next())
{
int indsol = It.Key();
const TopoDS_Shape& curshape = DStr.Shape(indsol);
NCollection_List<TopoDS_Shape>::Iterator its = myCoup->Merged(curshape, TopAbs_IN);
if (!its.More())
{
B1.Add(myShapeResult, curshape);
}
else
{
// If the old type of Shape is Shell, Shell is placed instead of Solid,
// However there is a problem for compound of open Shell.
while (its.More())
{
const TopAbs_ShapeEnum letype = curshape.ShapeType();
if (letype == TopAbs_SHELL)
{
TopExp_Explorer expsh2(its.Value(), TopAbs_SHELL);
const TopoDS_Shape& cursh = expsh2.Current();
B1.Add(myShapeResult, cursh);
its.Next();
}
else
{
B1.Add(myShapeResult, its.Value());
its.Next();
}
}
}
}
}
else
{
done = false;
B1.MakeCompound(TopoDS::Compound(badShape));
for (It = NCollection_Map<int>::Iterator(MapIndSo); It.More(); It.Next())
{
int indsol = It.Key();
const TopoDS_Shape& curshape = DStr.Shape(indsol);
NCollection_List<TopoDS_Shape>::Iterator its = myCoup->Merged(curshape, TopAbs_IN);
if (!its.More())
{
B1.Add(badShape, curshape);
}
else
{
while (its.More())
{
B1.Add(badShape, its.Value());
its.Next();
}
}
}
}
// Regularities are coded after cutting.
SetRegul();
}
}
// Inspect the new faces to provide sameparameter
// if it is necessary
if (IsDone())
{
double SameParTol = Precision::Confusion();
int aNbSurfaces, iF;
NCollection_List<TopoDS_Shape>::Iterator aIt;
//
aNbSurfaces = myDS->NbSurfaces();
for (iF = 1; iF <= aNbSurfaces; ++iF)
{
const NCollection_List<TopoDS_Shape>& aLF = myCoup->NewFaces(iF);
aIt.Initialize(aLF);
for (; aIt.More(); aIt.Next())
{
const TopoDS_Shape& aF = aIt.Value();
BRepLib::SameParameter(aF, SameParTol, true);
ShapeFix::SameParameter(aF, false, SameParTol);
}
}
}
}
//=======================================================================
// function : PerformSingularCorner
// purpose : Load vertex and degenerated edges.
//=======================================================================
void ChFi3d_Builder::PerformSingularCorner(const int Index)
{
NCollection_List<occ::handle<ChFiDS_Stripe>>::Iterator It;
occ::handle<ChFiDS_Stripe> stripe;
TopOpeBRepDS_DataStructure& DStr = myDS->ChangeDS();
const TopoDS_Vertex& Vtx = myVDataMap.FindKey(Index);
occ::handle<ChFiDS_SurfData> Fd;
int i, Icurv;
int Ivtx = 0;
for (It.Initialize(myVDataMap(Index)), i = 0; It.More(); It.Next(), i++)
{
stripe = It.Value();
// SurfData concerned and its CommonPoints,
int sens = 0;
int num = ChFi3d_IndexOfSurfData(Vtx, stripe, sens);
bool isfirst = (sens == 1);
Fd = stripe->SetOfSurfData()->Sequence().Value(num);
const ChFiDS_CommonPoint& CV1 = Fd->Vertex(isfirst, 1);
const ChFiDS_CommonPoint& CV2 = Fd->Vertex(isfirst, 2);
// Is it always degenerated ?
if (CV1.Point().IsEqual(CV2.Point(), 0))
{
// if yes the vertex is stored in the stripe
// and the edge at end is created
if (i == 0)
{
Ivtx = ChFi3d_IndexPointInDS(CV1, DStr);
}
double tolreached;
double Pardeb, Parfin;
gp_Pnt2d VOnS1, VOnS2;
occ::handle<Geom_Curve> C3d;
occ::handle<Geom2d_Curve> PCurv;
TopOpeBRepDS_Curve Crv;
if (isfirst)
{
VOnS1 =
Fd->InterferenceOnS1().PCurveOnSurf()->Value(Fd->InterferenceOnS1().FirstParameter());
VOnS2 =
Fd->InterferenceOnS2().PCurveOnSurf()->Value(Fd->InterferenceOnS2().FirstParameter());
}
else
{
VOnS1 =
Fd->InterferenceOnS1().PCurveOnSurf()->Value(Fd->InterferenceOnS1().LastParameter());
VOnS2 =
Fd->InterferenceOnS2().PCurveOnSurf()->Value(Fd->InterferenceOnS2().LastParameter());
}
ChFi3d_ComputeArete(CV1,
VOnS1,
CV2,
VOnS2,
DStr.Surface(Fd->Surf()).Surface(),
C3d,
PCurv,
Pardeb,
Parfin,
tolapp3d,
tolapp2d,
tolreached,
0);
Crv = TopOpeBRepDS_Curve(C3d, tolreached);
Icurv = DStr.AddCurve(Crv);
stripe->SetCurve(Icurv, isfirst);
stripe->SetParameters(isfirst, Pardeb, Parfin);
stripe->ChangePCurve(isfirst) = PCurv;
stripe->SetIndexPoint(Ivtx, isfirst, 1);
stripe->SetIndexPoint(Ivtx, isfirst, 2);
}
}
}
//=================================================================================================
void ChFi3d_Builder::PerformFilletOnVertex(const int Index)
{
NCollection_List<occ::handle<ChFiDS_Stripe>>::Iterator It;
occ::handle<ChFiDS_Stripe> stripe;
occ::handle<ChFiDS_Spine> sp;
const TopoDS_Vertex& Vtx = myVDataMap.FindKey(Index);
occ::handle<ChFiDS_SurfData> Fd;
int i;
bool nondegenere = true;
bool toujoursdegenere = true;
bool isfirst = false;
for (It.Initialize(myVDataMap(Index)), i = 0; It.More(); It.Next(), i++)
{
stripe = It.Value();
sp = stripe->Spine();
// SurfData and its CommonPoints,
int sens = 0;
int num = ChFi3d_IndexOfSurfData(Vtx, stripe, sens);
isfirst = (sens == 1);
Fd = stripe->SetOfSurfData()->Sequence().Value(num);
const ChFiDS_CommonPoint& CV1 = Fd->Vertex(isfirst, 1);
const ChFiDS_CommonPoint& CV2 = Fd->Vertex(isfirst, 2);
// Is it always degenerated ?
if (CV1.Point().IsEqual(CV2.Point(), 0))
{
nondegenere = false;
}
else
{
toujoursdegenere = false;
}
}
// calcul du nombre de faces = nombre d'aretes
/* NCollection_List<TopoDS_Shape>::Iterator ItF,JtF,ItE;
int nbf = 0, jf = 0;
for (ItF.Initialize(myVFMap(Vtx)); ItF.More(); ItF.Next()){
jf++;
int kf = 1;
const TopoDS_Shape& cur = ItF.Value();
for (JtF.Initialize(myVFMap(Vtx)); JtF.More() && (kf < jf); JtF.Next(), kf++){
if(cur.IsSame(JtF.Value())) break;
}
if(kf == jf) nbf++;
}
int nba=myVEMap(Vtx).Extent();
for (ItE.Initialize(myVEMap(Vtx)); ItE.More(); ItE.Next()){
const TopoDS_Edge& cur = TopoDS::Edge(ItE.Value());
if (BRep_Tool::Degenerated(cur)) nba--;
}
nba=nba/2;*/
int nba = ChFi3d_NumberOfSharpEdges(Vtx, myVEMap, myEFMap);
if (nondegenere)
{ // Normal processing
switch (i)
{
case 1: {
if (sp->Status(isfirst) == ChFiDS_FreeBoundary)
{
return;
}
if (nba > 3)
{
PerformIntersectionAtEnd(Index);
}
else
{
if (MoreSurfdata(Index))
{
PerformMoreSurfdata(Index);
}
else
{
PerformOneCorner(Index);
}
}
}
break;
case 2: {
if (nba > 3)
{
PerformMoreThreeCorner(Index, i);
}
else
{
PerformTwoCorner(Index);
}
}
break;
case 3: {
if (nba > 3)
{
PerformMoreThreeCorner(Index, i);
}
else
{
PerformThreeCorner(Index);
}
}
break;
default: {
PerformMoreThreeCorner(Index, i);
}
}
}
else
{ // Single case processing
if (toujoursdegenere)
{
PerformSingularCorner(Index);
}
else
{
PerformMoreThreeCorner(Index, i); // Last chance...
}
}
}
//=================================================================================================
void ChFi3d_Builder::Reset()
{
done = false;
myVDataMap.Clear();
myRegul.Clear();
myEVIMap.Clear();
badstripes.Clear();
badvertices.Clear();
NCollection_List<occ::handle<ChFiDS_Stripe>>::Iterator itel;
for (itel.Initialize(myListStripe); itel.More();)
{
if (!itel.Value()->Spine().IsNull())
{
itel.Value()->Reset();
itel.Next();
}
else
{
myListStripe.Remove(itel);
}
}
}
//=================================================================================================
const NCollection_List<TopoDS_Shape>& ChFi3d_Builder::Generated(const TopoDS_Shape& EouV)
{
myGenerated.Clear();
if (EouV.IsNull())
{
return myGenerated;
}
if (EouV.ShapeType() != TopAbs_EDGE && EouV.ShapeType() != TopAbs_VERTEX)
{
return myGenerated;
}
if (myEVIMap.IsBound(EouV))
{
const NCollection_List<int>& L = myEVIMap.Find(EouV);
NCollection_List<int>::Iterator IL;
for (IL.Initialize(L); IL.More(); IL.Next())
{
int I = IL.Value();
const NCollection_List<TopoDS_Shape>& LS = myCoup->NewFaces(I);
NCollection_List<TopoDS_Shape>::Iterator ILS;
for (ILS.Initialize(LS); ILS.More(); ILS.Next())
{
myGenerated.Append(ILS.Value());
}
}
}
return myGenerated;
}