Loading files
f2929057eThis file is pinned to the selected release. Download the original to open it in your design tool.
// Created on: 2000-02-11
// Created by: Peter KURNEV
// Copyright (c) 2000-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 <Adaptor3d_CurveOnSurface.hxx>
#include <Adaptor3d_Curve.hxx>
#include <BRep_GCurve.hxx>
#include <BRep_TEdge.hxx>
#include <BRepCheck_Wire.hxx>
#include <Extrema_LocateExtPC.hxx>
#include <Geom2dAdaptor.hxx>
#include <Geom2dAdaptor_Curve.hxx>
#include <Geom_Plane.hxx>
#include <Geom_RectangularTrimmedSurface.hxx>
#include <Geom_Surface.hxx>
#include <Geom_TrimmedCurve.hxx>
#include <GeomAdaptor_Curve.hxx>
#include <GeomAdaptor_Surface.hxx>
#include <GeomProjLib.hxx>
#include <gp_Pnt.hxx>
#include <gp_Vec.hxx>
#include <ProjLib_ProjectedCurve.hxx>
#include <TopExp.hxx>
#include <TopExp_Explorer.hxx>
#include <TopLoc_Location.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Shape.hxx>
#include <TopOpeBRepBuild_Tools.hxx>
#include <TopOpeBRepTool_ShapeClassifier.hxx>
#include <TopTools_ShapeMapHasher.hxx>
#include <NCollection_IndexedMap.hxx>
static void CheckEdge(const TopoDS_Edge& E, const double aMaxTol);
static void CorrectEdgeTolerance(const TopoDS_Edge& myShape,
const TopoDS_Face& S,
const double aMaxTol);
static bool Validate(const Adaptor3d_Curve& CRef,
const Adaptor3d_Curve& Other,
const double Tol,
const bool SameParameter,
double& aNewTolerance);
//=================================================================================================
void TopOpeBRepBuild_Tools::CorrectTolerances(const TopoDS_Shape& aShape, const double aMaxTol)
{
TopOpeBRepBuild_Tools::CorrectPointOnCurve(aShape, aMaxTol);
TopOpeBRepBuild_Tools::CorrectCurveOnSurface(aShape, aMaxTol);
}
//=================================================================================================
void TopOpeBRepBuild_Tools::CorrectPointOnCurve(const TopoDS_Shape& S, const double aMaxTol)
{
int i, aNb;
NCollection_IndexedMap<TopoDS_Shape, TopTools_ShapeMapHasher> Edges;
TopExp::MapShapes(S, TopAbs_EDGE, Edges);
aNb = Edges.Extent();
for (i = 1; i <= aNb; i++)
{
const TopoDS_Edge& E = TopoDS::Edge(Edges(i));
CheckEdge(E, aMaxTol);
}
}
//=================================================================================================
void TopOpeBRepBuild_Tools::CorrectCurveOnSurface(const TopoDS_Shape& S, const double aMaxTol)
{
int i, aNbFaces, j, aNbEdges;
NCollection_IndexedMap<TopoDS_Shape, TopTools_ShapeMapHasher> Faces;
TopExp::MapShapes(S, TopAbs_FACE, Faces);
aNbFaces = Faces.Extent();
for (i = 1; i <= aNbFaces; i++)
{
const TopoDS_Face& F = TopoDS::Face(Faces(i));
NCollection_IndexedMap<TopoDS_Shape, TopTools_ShapeMapHasher> Edges;
TopExp::MapShapes(F, TopAbs_EDGE, Edges);
aNbEdges = Edges.Extent();
for (j = 1; j <= aNbEdges; j++)
{
const TopoDS_Edge& E = TopoDS::Edge(Edges(j));
CorrectEdgeTolerance(E, F, aMaxTol);
}
}
}
//=================================================================================================
void CorrectEdgeTolerance(const TopoDS_Edge& myShape, const TopoDS_Face& S, const double aMaxTol)
{
//
// 1. Minimum of conditions to Perform
occ::handle<BRep_CurveRepresentation> myCref;
occ::handle<Adaptor3d_Curve> myHCurve;
myCref.Nullify();
occ::handle<BRep_TEdge>& TE = *((occ::handle<BRep_TEdge>*)&myShape.TShape());
NCollection_List<occ::handle<BRep_CurveRepresentation>>::Iterator itcr(TE->Curves());
bool Degenerated, SameParameter, SameRange;
int unique = 0;
Degenerated = TE->Degenerated();
SameParameter = TE->SameParameter();
SameRange = TE->SameRange();
if (!SameRange && SameParameter)
{
return;
}
while (itcr.More())
{
const occ::handle<BRep_CurveRepresentation>& cr = itcr.Value();
if (cr->IsCurve3D())
{
unique++;
if (myCref.IsNull() && !cr->Curve3D().IsNull())
{
myCref = cr;
}
}
itcr.Next();
}
if (unique == 0)
{
return; //...No3DCurve
}
if (unique > 1)
{
return; //...Multiple3DCurve;
}
if (myCref.IsNull() && !Degenerated)
{
itcr.Initialize(TE->Curves());
while (itcr.More())
{
const occ::handle<BRep_CurveRepresentation>& cr = itcr.Value();
if (cr->IsCurveOnSurface())
{
myCref = cr;
break;
}
itcr.Next();
}
}
else if (!myCref.IsNull() && Degenerated)
{
return; //...InvalidDegeneratedFlag;
}
if (!myCref.IsNull())
{
occ::handle<BRep_GCurve> GCref(occ::down_cast<BRep_GCurve>(myCref));
double First, Last;
GCref->Range(First, Last);
if (Last <= First)
{
myCref.Nullify();
return; // InvalidRange;
}
else
{
if (myCref->IsCurve3D())
{
occ::handle<Geom_Curve> C3d = occ::down_cast<Geom_Curve>(
myCref->Curve3D()->Transformed(myCref->Location().Transformation()));
GeomAdaptor_Curve GAC3d(C3d, First, Last);
myHCurve = new GeomAdaptor_Curve(GAC3d);
}
else
{ // curve on surface
occ::handle<Geom_Surface> Sref = myCref->Surface();
Sref = occ::down_cast<Geom_Surface>(Sref->Transformed(myCref->Location().Transformation()));
const occ::handle<Geom2d_Curve>& PCref = myCref->PCurve();
occ::handle<GeomAdaptor_Surface> GAHSref = new GeomAdaptor_Surface(Sref);
occ::handle<Geom2dAdaptor_Curve> GHPCref = new Geom2dAdaptor_Curve(PCref, First, Last);
Adaptor3d_CurveOnSurface ACSref(GHPCref, GAHSref);
myHCurve = new Adaptor3d_CurveOnSurface(ACSref);
}
}
}
//===============================================
// 2. Tolerances in InContext
{
if (myCref.IsNull())
{
return;
}
bool ok = true;
double Tol = BRep_Tool::Tolerance(TopoDS::Edge(myShape));
double aNewTol = Tol;
double First = myHCurve->FirstParameter();
double Last = myHCurve->LastParameter();
occ::handle<BRep_TFace>& TF = *((occ::handle<BRep_TFace>*)&S.TShape());
const TopLoc_Location& Floc = S.Location();
const TopLoc_Location& TFloc = TF->Location();
const occ::handle<Geom_Surface>& Su = TF->Surface();
TopLoc_Location L = (Floc * TFloc).Predivided(myShape.Location());
bool pcurvefound = false;
itcr.Initialize(TE->Curves());
while (itcr.More())
{
const occ::handle<BRep_CurveRepresentation>& cr = itcr.Value();
if (cr != myCref && cr->IsCurveOnSurface(Su, L))
{
pcurvefound = true;
occ::handle<BRep_GCurve> GC(occ::down_cast<BRep_GCurve>(cr));
double f, l;
GC->Range(f, l);
if (SameRange && (f != First || l != Last))
{
return; // BRepCheck_InvalidSameRangeFlag;
}
occ::handle<Geom_Surface> Sb = cr->Surface();
Sb = occ::down_cast<Geom_Surface>(Su->Transformed(L.Transformation()));
occ::handle<Geom2d_Curve> PC = cr->PCurve();
occ::handle<GeomAdaptor_Surface> GAHS = new GeomAdaptor_Surface(Sb);
occ::handle<Geom2dAdaptor_Curve> GHPC = new Geom2dAdaptor_Curve(PC, f, l);
Adaptor3d_CurveOnSurface ACS(GHPC, GAHS);
ok = Validate(*myHCurve, ACS, Tol, SameParameter, aNewTol);
if (ok)
{
// printf("(Edge,1) Tolerance=%15.10lg\n", aNewTol);
if (aNewTol < aMaxTol)
{
TE->UpdateTolerance(aNewTol);
}
}
if (cr->IsCurveOnClosedSurface())
{
// checkclosed = true;
GHPC->Load(cr->PCurve2(), f, l); // same bounds
ACS.Load(GHPC, GAHS); // sans doute inutile
ok = Validate(*myHCurve, ACS, Tol, SameParameter, aNewTol);
if (ok)
{
if (aNewTol < aMaxTol)
{
TE->UpdateTolerance(aNewTol);
}
}
}
}
itcr.Next();
}
if (!pcurvefound)
{
occ::handle<Geom_Plane> P;
occ::handle<Standard_Type> styp = Su->DynamicType();
if (styp == STANDARD_TYPE(Geom_RectangularTrimmedSurface))
{
P = occ::down_cast<Geom_Plane>(
occ::down_cast<Geom_RectangularTrimmedSurface>(Su)->BasisSurface());
}
else
{
P = occ::down_cast<Geom_Plane>(Su);
}
if (P.IsNull())
{ // not a plane
return; // BRepCheck::Add(lst,BRepCheck_NoCurveOnSurface);
}
else
{ // on fait la projection a la volee, comme BRep_Tool
P = occ::down_cast<Geom_Plane>(P->Transformed(L.Transformation()));
// on projette Cref sur ce plan
occ::handle<GeomAdaptor_Surface> GAHS = new GeomAdaptor_Surface(P);
// Dub - Normalement myHCurve est une GeomAdaptor_Curve
occ::handle<GeomAdaptor_Curve> Gac = occ::down_cast<GeomAdaptor_Curve>(myHCurve);
occ::handle<Geom_Curve> C3d = Gac->Curve();
occ::handle<Geom_Curve> ProjOnPlane =
GeomProjLib::ProjectOnPlane(new Geom_TrimmedCurve(C3d, First, Last),
P,
P->Position().Direction(),
true);
occ::handle<GeomAdaptor_Curve> aHCurve = new GeomAdaptor_Curve(ProjOnPlane);
ProjLib_ProjectedCurve proj(GAHS, aHCurve);
occ::handle<Geom2d_Curve> PC = Geom2dAdaptor::MakeCurve(proj);
occ::handle<Geom2dAdaptor_Curve> GHPC =
new Geom2dAdaptor_Curve(PC, myHCurve->FirstParameter(), myHCurve->LastParameter());
Adaptor3d_CurveOnSurface ACS(GHPC, GAHS);
ok = Validate(*myHCurve, ACS, Tol, true, aNewTol); // voir dub...
if (ok)
{
if (aNewTol < aMaxTol)
{
TE->UpdateTolerance(aNewTol);
}
}
}
} // end of if (!pcurvefound) {
} // end of 2. Tolerances in InContext
}
#define NCONTROL 23
//=================================================================================================
bool Validate(const Adaptor3d_Curve& CRef,
const Adaptor3d_Curve& Other,
const double Tol,
const bool SameParameter,
double& aNewTolerance)
{
double First, Last, MaxDistance, aD;
First = CRef.FirstParameter();
Last = CRef.LastParameter();
MaxDistance = Tol * Tol;
int i, aNC1 = NCONTROL - 1;
bool aFlag = false;
bool proj = (!SameParameter || First != Other.FirstParameter() || Last != Other.LastParameter());
//
// 1.
if (!proj)
{
for (i = 0; i < NCONTROL; i++)
{
double prm = ((aNC1 - i) * First + i * Last) / aNC1;
gp_Pnt pref = CRef.Value(prm);
gp_Pnt pother = Other.Value(prm);
aD = pref.SquareDistance(pother);
if (aD > MaxDistance)
{
MaxDistance = aD;
aFlag = true;
}
}
}
//
// 2.
else
{
Extrema_LocateExtPC refd, otherd;
double OFirst, OLast;
OFirst = Other.FirstParameter();
OLast = Other.LastParameter();
gp_Pnt pd = CRef.Value(First);
gp_Pnt pdo = Other.Value(OFirst);
aD = pd.SquareDistance(pdo);
if (aD > MaxDistance)
{
MaxDistance = aD;
aFlag = true;
}
pd = CRef.Value(Last);
pdo = Other.Value(OLast);
aD = pd.SquareDistance(pdo);
if (aD > MaxDistance)
{
MaxDistance = aD;
aFlag = true;
}
refd.Initialize(CRef, First, Last, CRef.Resolution(Tol));
otherd.Initialize(Other, OFirst, OLast, Other.Resolution(Tol));
for (i = 2; i < aNC1; i++)
{
double rprm = ((aNC1 - i) * First + i * Last) / aNC1;
gp_Pnt pref = CRef.Value(rprm);
double oprm = ((aNC1 - i) * OFirst + i * OLast) / aNC1;
gp_Pnt pother = Other.Value(oprm);
refd.Perform(pother, rprm);
if (!refd.IsDone() || refd.SquareDistance() > Tol * Tol)
{
if (refd.IsDone())
{
aD = refd.SquareDistance();
if (aD > MaxDistance)
{
aFlag = true;
MaxDistance = aD;
}
}
}
otherd.Perform(pref, oprm);
if (!otherd.IsDone() || otherd.SquareDistance() > Tol * Tol)
{
if (otherd.IsDone())
{
aD = otherd.SquareDistance();
if (aD > MaxDistance)
{
aFlag = true;
MaxDistance = aD;
}
}
}
}
}
if (aFlag)
{
aD = sqrt(MaxDistance);
aNewTolerance = aD * 1.05;
}
return aFlag;
}
//=======================================================================
// Function : CheckEdge
// purpose : Correct tolerances for Vertices on Edge
//=======================================================================
void CheckEdge(const TopoDS_Edge& Ed, const double aMaxTol)
{
TopoDS_Edge E = Ed;
E.Orientation(TopAbs_FORWARD);
gp_Pnt Controlp;
TopExp_Explorer aVExp;
aVExp.Init(E, TopAbs_VERTEX);
for (; aVExp.More(); aVExp.Next())
{
TopoDS_Vertex aVertex = TopoDS::Vertex(aVExp.Current());
occ::handle<BRep_TVertex>& TV = *((occ::handle<BRep_TVertex>*)&aVertex.TShape());
const gp_Pnt& prep = TV->Pnt();
double Tol, aD2, aNewTolerance, dd;
Tol = BRep_Tool::Tolerance(aVertex);
Tol = std::max(Tol, BRep_Tool::Tolerance(E));
dd = 0.1 * Tol;
Tol *= Tol;
const TopLoc_Location& Eloc = E.Location();
NCollection_List<occ::handle<BRep_PointRepresentation>>::Iterator itpr;
occ::handle<BRep_TEdge>& TE = *((occ::handle<BRep_TEdge>*)&E.TShape());
NCollection_List<occ::handle<BRep_CurveRepresentation>>::Iterator itcr(TE->Curves());
while (itcr.More())
{
const occ::handle<BRep_CurveRepresentation>& cr = itcr.Value();
const TopLoc_Location& loc = cr->Location();
TopLoc_Location L = (Eloc * loc).Predivided(aVertex.Location());
if (cr->IsCurve3D())
{
const occ::handle<Geom_Curve>& C = cr->Curve3D();
if (!C.IsNull())
{
itpr.Initialize(TV->Points());
while (itpr.More())
{
const occ::handle<BRep_PointRepresentation>& pr = itpr.Value();
if (pr->IsPointOnCurve(C, L))
{
Controlp = C->Value(pr->Parameter());
Controlp.Transform(L.Transformation());
aD2 = prep.SquareDistance(Controlp);
if (aD2 > Tol)
{
aNewTolerance = sqrt(aD2) + dd;
if (aNewTolerance < aMaxTol)
{
TV->UpdateTolerance(aNewTolerance);
}
}
}
itpr.Next();
}
TopAbs_Orientation orv = aVertex.Orientation();
if (orv == TopAbs_FORWARD || orv == TopAbs_REVERSED)
{
occ::handle<BRep_GCurve> GC(occ::down_cast<BRep_GCurve>(cr));
if (orv == TopAbs_FORWARD)
{
Controlp = C->Value(GC->First());
}
else
{
Controlp = C->Value(GC->Last());
}
Controlp.Transform(L.Transformation());
aD2 = prep.SquareDistance(Controlp);
if (aD2 > Tol)
{
aNewTolerance = sqrt(aD2) + dd;
if (aNewTolerance < aMaxTol)
{
TV->UpdateTolerance(aNewTolerance);
}
}
}
}
}
itcr.Next();
}
}
}
//=================================================================================================
bool TopOpeBRepBuild_Tools::CheckFaceClosed2d(const TopoDS_Face& theFace)
{
bool isClosed = true;
TopExp_Explorer ex(theFace, TopAbs_WIRE);
for (; ex.More() && isClosed; ex.Next())
{
const TopoDS_Wire& aW = TopoDS::Wire(ex.Current());
BRepCheck_Wire aWChk(aW);
BRepCheck_Status aStatus = aWChk.Orientation(theFace);
if (aStatus != BRepCheck_NoError)
{
isClosed = false;
}
}
return isClosed;
}