1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-04-21 10:13:43 +03:00
occt/src/StepToTopoDS/StepToTopoDS_GeometricTool.cxx

400 lines
14 KiB
C++

// Created on: 1995-01-06
// Created by: Frederic MAUPAS
// Copyright (c) 1995-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.
//pdn 11.01.99 #144 bm1_pe_t4 protection of exceptions in draw
// abv 13.04.99 S4136: eliminate BRepAPI::Precision()
#include <BRep_Builder.hxx>
#include <BRep_Tool.hxx>
#include <BRepTools.hxx>
#include <BRepTools_WireExplorer.hxx>
#include <ElCLib.hxx>
#include <ElSLib.hxx>
#include <Geom2d_Curve.hxx>
#include <Geom2d_Line.hxx>
#include <Geom2d_TrimmedCurve.hxx>
#include <Geom2dAPI_InterCurveCurve.hxx>
#include <Geom2dAPI_ProjectPointOnCurve.hxx>
#include <Geom_BoundedCurve.hxx>
#include <Geom_BSplineCurve.hxx>
#include <Geom_BSplineSurface.hxx>
#include <Geom_ConicalSurface.hxx>
#include <Geom_Curve.hxx>
#include <Geom_CylindricalSurface.hxx>
#include <Geom_Line.hxx>
#include <Geom_Plane.hxx>
#include <Geom_SphericalSurface.hxx>
#include <Geom_ToroidalSurface.hxx>
#include <GeomAbs_CurveType.hxx>
#include <GeomAbs_Shape.hxx>
#include <GeomAdaptor_Curve.hxx>
#include <GeomAPI_ProjectPointOnCurve.hxx>
#include <GeomAPI_ProjectPointOnSurf.hxx>
#include <gp_Vec2d.hxx>
#include <Precision.hxx>
#include <Standard_ErrorHandler.hxx>
#include <Standard_Failure.hxx>
#include <StepGeom_CartesianPoint.hxx>
#include <StepGeom_Direction.hxx>
#include <StepGeom_Line.hxx>
#include <StepGeom_Pcurve.hxx>
#include <StepGeom_PcurveOrSurface.hxx>
#include <StepGeom_SeamCurve.hxx>
#include <StepGeom_Surface.hxx>
#include <StepGeom_SurfaceCurve.hxx>
#include <StepGeom_Vector.hxx>
#include <StepRepr_DefinitionalRepresentation.hxx>
#include <StepShape_Edge.hxx>
#include <StepShape_EdgeLoop.hxx>
#include <StepShape_OrientedEdge.hxx>
#include <StepToTopoDS.hxx>
#include <StepToTopoDS_GeometricTool.hxx>
#include <TopExp.hxx>
#include <TopExp_Explorer.hxx>
#include <TopoDS.hxx>
#include <Transfer_TransientProcess.hxx>
// ----------------------------------------------------------------------------
// Method : HasPCurve
// Purpose : returns true if the surface curve has at least one pcurve lying
//on the surface
// ----------------------------------------------------------------------------
Standard_Integer StepToTopoDS_GeometricTool::PCurve
(const Handle(StepGeom_SurfaceCurve)& SurfCurve,
const Handle(StepGeom_Surface)& BasisSurf,
Handle(StepGeom_Pcurve)& thePCurve, const Standard_Integer last)
{
Standard_Integer NbAssGeom = SurfCurve->NbAssociatedGeometry();
thePCurve.Nullify();
for (Standard_Integer i= last+1; i<=NbAssGeom; i++) {
thePCurve = SurfCurve->AssociatedGeometryValue(i).Pcurve();
if (!thePCurve.IsNull()) {
if (thePCurve->BasisSurface() == BasisSurf) return i;
}
}
thePCurve.Nullify();
return 0;
}
// ----------------------------------------------------------------------------
// Method : IsSeamCurve
// Purpose : Two edges of the same wire references the same oriented edge
// Then the surface_curve is a seam curve
// ----------------------------------------------------------------------------
Standard_Boolean StepToTopoDS_GeometricTool::IsSeamCurve
(const Handle(StepGeom_SurfaceCurve)& SurfCurve,
const Handle(StepGeom_Surface)& Surf,
const Handle(StepShape_Edge)& StepEdge,
const Handle(StepShape_EdgeLoop)& EdgeLoop)
{
if (SurfCurve->IsKind(STANDARD_TYPE(StepGeom_SeamCurve)))
return Standard_True;
if (SurfCurve->NbAssociatedGeometry() != 2) return Standard_False;
Handle(StepGeom_Pcurve) StepPCurve1 =
SurfCurve->AssociatedGeometryValue(1).Pcurve();
Handle(StepGeom_Pcurve) StepPCurve2 =
SurfCurve->AssociatedGeometryValue(2).Pcurve();
// Do the two pcurves lye on the same surface ?
if ((!StepPCurve1.IsNull() && !StepPCurve2.IsNull()) &&
(StepPCurve1->BasisSurface() == Surf) &&
(StepPCurve2->BasisSurface()== Surf)) {
Standard_Integer NbEdge = EdgeLoop->NbEdgeList();
Standard_Integer nbOE = 0;
Handle(StepShape_OrientedEdge) OrEdge;
for (Standard_Integer i = 1; i <= NbEdge; i ++ ) {
OrEdge = EdgeLoop->EdgeListValue(i);
if (StepEdge == OrEdge->EdgeElement()) nbOE ++;
}
// two oriented edges of the same wire share the same edge
if (nbOE == 2) return Standard_True;
}
return Standard_False;
}
// ----------------------------------------------------------------------------
// Method : IsLikeSeam
// Purpose : The two pcurves lies on the same surface but on different wires.
// This is typical situation in CATIA BRep : a cylinder is coded
// with two faces on the same 'Closed' BSplineSurf, which in the
// range of gp_Resolution is not identified as closed
// ----------------------------------------------------------------------------
Standard_Boolean StepToTopoDS_GeometricTool::IsLikeSeam
(const Handle(StepGeom_SurfaceCurve)& SurfCurve,
const Handle(StepGeom_Surface)& Surf,
const Handle(StepShape_Edge)& StepEdge,
const Handle(StepShape_EdgeLoop)& EdgeLoop)
{
if (SurfCurve->NbAssociatedGeometry() != 2) return Standard_False;
Handle(StepGeom_Pcurve) StepPCurve1 =
SurfCurve->AssociatedGeometryValue(1).Pcurve();
Handle(StepGeom_Pcurve) StepPCurve2 =
SurfCurve->AssociatedGeometryValue(2).Pcurve();
// Do the two pcurves lye on the same surface ?
if ((!StepPCurve1.IsNull() && !StepPCurve2.IsNull()) &&
(StepPCurve1->BasisSurface() == Surf) &&
(StepPCurve2->BasisSurface() == Surf)) {
Standard_Integer NbEdge = EdgeLoop->NbEdgeList();
Standard_Integer nbOE = 0;
Handle(StepShape_OrientedEdge) OrEdge;
for (Standard_Integer i = 1; i <= NbEdge; i ++ ) {
OrEdge = EdgeLoop->EdgeListValue(i);
if (StepEdge == OrEdge->EdgeElement()) nbOE ++;
}
// the two oriented edges are not in the same wire
if (nbOE == 1) {
// check is the two pcurve are not indentical ?
Handle(StepGeom_Line) line1 = Handle(StepGeom_Line)::DownCast
(StepPCurve1->ReferenceToCurve()->ItemsValue(1));
Handle(StepGeom_Line) line2 = Handle(StepGeom_Line)::DownCast
(StepPCurve2->ReferenceToCurve()->ItemsValue(1));
if (!line1.IsNull() && !line2.IsNull()) {
// Same Origin in X OR Y && Same Vector ??
// WITHIN A given tolerance !!!
Standard_Real DeltaX = Abs(line1->Pnt()->CoordinatesValue(1) -
line2->Pnt()->CoordinatesValue(1));
Standard_Real DeltaY = Abs(line1->Pnt()->CoordinatesValue(2) -
line2->Pnt()->CoordinatesValue(2));
Standard_Real DeltaDirX =
Abs(line1->Dir()->Orientation()->DirectionRatiosValue(1) -
line2->Dir()->Orientation()->DirectionRatiosValue(1));
Standard_Real DeltaDirY =
Abs(line1->Dir()->Orientation()->DirectionRatiosValue(2) -
line2->Dir()->Orientation()->DirectionRatiosValue(2));
Standard_Real preci2d = Precision::PConfusion(); //:S4136: Parametric(BRepAPI::Precision(),10);
if ((DeltaX < preci2d) || (DeltaY < preci2d))
return ((DeltaDirX < preci2d) && (DeltaDirY < preci2d));
else return Standard_False;
// Warning : la manipulation de tolerances dans ce contexte est un
// peu trop dangeureux.
// il serait preferable de plus de ne pas restreindre au
// cas de deux lignes.
// un mode plus convenable de detection serait de se servir
// des isos (ou bords naturels) de la surface de base
// et de detecter que les deux courbes se trouvent sur le
// bord de fermeture.
// il faut toutefois prevoir le cas ou les deux courbes
// sont confondues (ex : CATIA, "couture" de separation
// en deux faces d un support periodique.
// Ce travail reste evidement A FAIRE !!! ...
}
else return Standard_False;
}
return Standard_False;
}
return Standard_False;
}
// ----------------------------------------------------------------------------
// Method : UpdateParam3d
// Purpose : According to the type of curve update parameter (w1>w2)
// This situation occurs when an edge crosses the parametric origin.
// ----------------------------------------------------------------------------
Standard_Boolean StepToTopoDS_GeometricTool::UpdateParam3d(
const Handle(Geom_Curve)& theCurve,
Standard_Real& w1,
Standard_Real& w2,
const Standard_Real preci)
{
// w1 et/ou w2 peuvent etre en dehors des bornes naturelles de la courbe.
// On donnera alors la valeur en bout a w1 et/ou w2
Standard_Real cf = theCurve->FirstParameter();
Standard_Real cl = theCurve->LastParameter();
if (theCurve->IsKind(STANDARD_TYPE(Geom_BoundedCurve)) && !theCurve->IsClosed())
{
if (w1 < cf)
{
#ifdef OCCT_DEBUG
cout << "Update Edge First Parameter to Curve First Parameter" << endl;
#endif
w1 = cf;
}
else if (w1 > cl)
{
#ifdef OCCT_DEBUG
cout << "Update Edge First Parameter to Curve Last Parameter" << endl;
#endif
w1 = cl;
}
if (w2 < cf) {
#ifdef OCCT_DEBUG
cout << "Update Edge Last Parameter to Curve First Parameter" << endl;
#endif
w2 = cf;
}
else if (w2 > cl) {
#ifdef OCCT_DEBUG
cout << "Update Edge Last Parameter to Curve Last Parameter" << endl;
#endif
w2 = cl;
}
}
if (w1 < w2) return Standard_True;
if (theCurve->IsPeriodic())
{
ElCLib::AdjustPeriodic(cf, cl, Precision::PConfusion(), w1, w2); //:a7 abv 11 Feb 98: preci -> PConfusion()
}
else if (theCurve->IsClosed())
{
// l'un des points projecte se trouve sur l'origine du parametrage
// de la courbe 3D. L algo a donne cl +- preci au lieu de cf ou vice-versa
// DANGER precision 3d applique a une espace 1d
// w2 = cf au lieu de w2 = cl
if (Abs(w2 - cf) < Precision::PConfusion() /*preci*/)
{
w2 = cl;
}
// w1 = cl au lieu de w1 = cf
else if (Abs(w1 - cl) < Precision::PConfusion() /*preci*/)
{
w1 = cf;
}
// on se trouve dans un cas ou l origine est traversee
// illegal sur une courbe fermee non periodique
// on inverse quand meme les parametres !!!!!!
else
{
//:S4136 abv 20 Apr 99: r0701_ug.stp #6230: add check in 3d
if (theCurve->Value(w1).Distance(theCurve->Value(cf)) < preci)
{
w1 = cf;
}
if (theCurve->Value(w2).Distance(theCurve->Value(cl)) < preci)
{
w2 = cl;
}
if (fabs(w2 - w1) < Precision::PConfusion())
{
w1 = cf;
w2 = cl;
}
else if (w1 > w2)
{
#ifdef OCCT_DEBUG
cout << "Warning : parameter range of edge crossing non periodic curve origin" << endl;
#endif
Standard_Real tmp = w1;
w1 = w2;
w2 = tmp;
}
}
}
// The curve is closed within the 3D tolerance
else if (theCurve->IsKind(STANDARD_TYPE(Geom_BSplineCurve)))
{
Handle(Geom_BSplineCurve) aBSpline =
Handle(Geom_BSplineCurve)::DownCast(theCurve);
if (aBSpline->StartPoint().Distance(aBSpline->EndPoint()) <= preci)
{
//:S4136 <= BRepAPI::Precision()) {
// l'un des points projecte se trouve sur l'origine du parametrage
// de la courbe 3D. L algo a donne cl +- preci au lieu de cf ou vice-versa
// DANGER precision 3d applique a une espace 1d
// w2 = cf au lieu de w2 = cl
if (Abs(w2 - cf) < Precision::PConfusion())
{
w2 = cl;
}
// w1 = cl au lieu de w1 = cf
else if (Abs(w1 - cl) < Precision::PConfusion())
{
w1 = cf;
}
// on se trouve dans un cas ou l origine est traversee
// illegal sur une courbe fermee non periodique
// on inverse quand meme les parametres !!!!!!
else
{
#ifdef OCCT_DEBUG
cout << "Warning : parameter range of edge crossing non periodic curve origin" << endl;
#endif
Standard_Real tmp = w1;
w1 = w2;
w2 = tmp;
}
}
//abv 15.03.00 #72 bm1_pe_t4 protection of exceptions in draw
else if (w1 > w2)
{
#ifdef OCCT_DEBUG
cout << "Warning: parameter range is bad; curve reversed" << endl;
#endif
w1 = theCurve->ReversedParameter(w1);
w2 = theCurve->ReversedParameter(w2);
theCurve->Reverse();
}
//:j9 abv 11 Dec 98: PRO7747 #4875, after :j8: else
if (w1 == w2)
{ //gka 10.07.1998 file PRO7656 entity 33334
w1 = cf;
w2 = cl;
return Standard_False;
}
}
else
{
#ifdef OCCT_DEBUG
cout << "UpdateParam3d Failed" << endl;
cout << " - Curve Type : " << theCurve->DynamicType() << endl;
cout << " - Param 1 : " << w1 << endl;
cout << " - Param 2 : " << w2 << endl;
#endif
//abv 15.03.00 #72 bm1_pe_t4 protection of exceptions in draw
if (w1 > w2)
{
#ifdef OCCT_DEBUG
cout << "Warning: parameter range is bad; curve reversed" << endl;
#endif
w1 = theCurve->ReversedParameter(w1);
w2 = theCurve->ReversedParameter(w2);
theCurve->Reverse();
}
//pdn 11.01.99 #144 bm1_pe_t4 protection of exceptions in draw
if (w1 == w2)
{
w1 -= Precision::PConfusion();
w2 += Precision::PConfusion();
}
return Standard_False;
}
return Standard_True;
}