mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-08-24 13:50:49 +03:00
Compare commits
9 Commits
V7_8_1
...
CR0_MW_vrm
Author | SHA1 | Date | |
---|---|---|---|
|
df5c3611d6 | ||
|
069841b702 | ||
|
0d65441e56 | ||
|
11780e291c | ||
|
9fe7905d7a | ||
|
ff356178e2 | ||
|
dcf805dbb7 | ||
|
b930adbe57 | ||
|
1315aa6509 |
@@ -299,7 +299,6 @@ void AIS_ColoredShape::Compute (const Handle(PrsMgr_PresentationManager3d)& ,
|
||||
const Handle(Prs3d_Presentation)& thePrs,
|
||||
const Standard_Integer theMode)
|
||||
{
|
||||
thePrs->Clear();
|
||||
if (IsInfinite())
|
||||
{
|
||||
thePrs->SetInfiniteState (Standard_True);
|
||||
|
@@ -1501,8 +1501,8 @@ Standard_Real AIS_InteractiveContext::HLRAngle() const
|
||||
//function : SetDisplayMode
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
void AIS_InteractiveContext::SetDisplayMode (const AIS_DisplayMode theMode,
|
||||
const Standard_Boolean theToUpdateViewer)
|
||||
void AIS_InteractiveContext::SetDisplayMode(const Standard_Integer theMode,
|
||||
const Standard_Boolean theToUpdateViewer)
|
||||
{
|
||||
if (theMode == myDisplayMode)
|
||||
{
|
||||
|
@@ -672,7 +672,7 @@ public:
|
||||
//! object is displayed but no viewer will be updated.
|
||||
//! Note that display mode 3 is only used if you have an
|
||||
//! AIS_Textured Shape.
|
||||
Standard_EXPORT void SetDisplayMode (const AIS_DisplayMode AMode, const Standard_Boolean updateviewer = Standard_True);
|
||||
Standard_EXPORT void SetDisplayMode (const Standard_Integer AMode, const Standard_Boolean updateviewer = Standard_True);
|
||||
|
||||
|
||||
//! Sets the deviation coefficient aCoefficient.
|
||||
|
@@ -72,13 +72,17 @@ void BRepAdaptor_Surface::Initialize(const TopoDS_Face& F,
|
||||
{
|
||||
myFace = F;
|
||||
TopLoc_Location L;
|
||||
const Handle(Geom_Surface)& aSurface = BRep_Tool::Surface(F, L);
|
||||
if (aSurface.IsNull())
|
||||
return;
|
||||
|
||||
if (Restriction) {
|
||||
Standard_Real umin,umax,vmin,vmax;
|
||||
BRepTools::UVBounds(F,umin,umax,vmin,vmax);
|
||||
mySurf.Load(BRep_Tool::Surface(F,L),umin,umax,vmin,vmax);
|
||||
mySurf.Load(aSurface,umin,umax,vmin,vmax);
|
||||
}
|
||||
else
|
||||
mySurf.Load(BRep_Tool::Surface(F,L));
|
||||
mySurf.Load(aSurface);
|
||||
myTrsf = L.Transformation();
|
||||
}
|
||||
|
||||
|
@@ -74,7 +74,8 @@ void BRepTools::UVBounds(const TopoDS_Face& F,
|
||||
{
|
||||
Bnd_Box2d B;
|
||||
AddUVBounds(F,B);
|
||||
B.Get(UMin,VMin,UMax,VMax);
|
||||
if (!B.IsVoid())
|
||||
B.Get(UMin,VMin,UMax,VMax);
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
@@ -130,7 +131,11 @@ void BRepTools::AddUVBounds(const TopoDS_Face& FF, Bnd_Box2d& B)
|
||||
if (aBox.IsVoid()) {
|
||||
Standard_Real UMin,UMax,VMin,VMax;
|
||||
TopLoc_Location L;
|
||||
BRep_Tool::Surface(F,L)->Bounds(UMin,UMax,VMin,VMax);
|
||||
const Handle(Geom_Surface)& aSurf = BRep_Tool::Surface(F, L);
|
||||
if (aSurf.IsNull())
|
||||
return;
|
||||
|
||||
aSurf->Bounds(UMin,UMax,VMin,VMax);
|
||||
aBox.Update(UMin,VMin,UMax,VMax);
|
||||
}
|
||||
|
||||
|
@@ -74,8 +74,8 @@ static Standard_OStream& operator <<(Standard_OStream& OS, const gp_Pnt P)
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
|
||||
BinTools_ShapeSet::BinTools_ShapeSet(const Standard_Boolean isWithTriangles)
|
||||
:myFormatNb(3), myWithTriangles(isWithTriangles)
|
||||
BinTools_ShapeSet::BinTools_ShapeSet(const Standard_Boolean /*isWithTriangles*/)
|
||||
:myFormatNb(3), myWithTriangles(Standard_True/*isWithTriangles*/)
|
||||
{}
|
||||
|
||||
//=======================================================================
|
||||
@@ -90,9 +90,9 @@ BinTools_ShapeSet::~BinTools_ShapeSet()
|
||||
//function : SetWithTriangles
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
void BinTools_ShapeSet::SetWithTriangles(const Standard_Boolean isWithTriangles)
|
||||
void BinTools_ShapeSet::SetWithTriangles(const Standard_Boolean /*isWithTriangles*/)
|
||||
{
|
||||
myWithTriangles = isWithTriangles;
|
||||
myWithTriangles = Standard_True;//isWithTriangles;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
@@ -524,6 +524,12 @@ void BinTools_ShapeSet::Read(TopoDS_Shape& S, Standard_IStream& IS,
|
||||
anOrient = (TopAbs_Orientation)aChar;
|
||||
Standard_Integer anIndx;
|
||||
BinTools::GetInteger(IS, anIndx);
|
||||
Standard_Integer anInd = nbshapes - anIndx + 1;
|
||||
if (anInd < 1 || anInd > myShapes.Extent())
|
||||
{
|
||||
S = TopoDS_Shape();
|
||||
return;
|
||||
}
|
||||
S = myShapes(nbshapes - anIndx + 1);
|
||||
S.Orientation(anOrient);
|
||||
|
||||
@@ -732,6 +738,7 @@ void BinTools_ShapeSet::WriteGeometry(const TopoDS_Shape& S,
|
||||
const TopoDS_Face& F = TopoDS::Face(S);
|
||||
|
||||
if (!(TF->Surface()).IsNull()) {
|
||||
//OS << (Standard_Byte) 1;
|
||||
Standard_Boolean aNatRes = (BRep_Tool::NaturalRestriction(F)) ? Standard_True : Standard_False;
|
||||
BinTools::PutBool(OS, aNatRes);
|
||||
|
||||
@@ -740,6 +747,8 @@ void BinTools_ShapeSet::WriteGeometry(const TopoDS_Shape& S,
|
||||
BinTools::PutInteger(OS, mySurfaces.Index(TF->Surface()));
|
||||
BinTools::PutInteger(OS, Locations().Index(TF->Location()));
|
||||
}
|
||||
//else
|
||||
// OS << (Standard_Byte) 0;
|
||||
if (myWithTriangles) {
|
||||
if (!(TF->Triangulation()).IsNull()) {
|
||||
OS << (Standard_Byte) 2;
|
||||
@@ -1099,17 +1108,26 @@ void BinTools_ShapeSet::ReadGeometry(const TopAbs_ShapeEnum T,
|
||||
// create a face :
|
||||
TopoDS_Face& F = TopoDS::Face(S);
|
||||
myBuilder.MakeFace(F);
|
||||
BinTools::GetBool(IS, bval); //NaturalRestriction flag
|
||||
BinTools::GetReal(IS, tol);
|
||||
BinTools::GetInteger(IS, s); //surface indx
|
||||
BinTools::GetInteger(IS, l); //location indx
|
||||
if (!mySurfaces.Surface(s).IsNull()) {
|
||||
myBuilder.UpdateFace(TopoDS::Face(S),
|
||||
mySurfaces.Surface(s),
|
||||
Locations().Location(l),tol);
|
||||
myBuilder.NaturalRestriction(TopoDS::Face(S),bval );
|
||||
}
|
||||
|
||||
//Standard_Byte aByte = (Standard_Byte)IS.get();
|
||||
//if (aByte == 1)
|
||||
//{
|
||||
BinTools::GetBool(IS, bval); //NaturalRestriction flag
|
||||
BinTools::GetReal(IS, tol);
|
||||
BinTools::GetInteger(IS, s); //surface indx
|
||||
BinTools::GetInteger(IS, l); //location indx
|
||||
if (!mySurfaces.Surface(s).IsNull()) {
|
||||
myBuilder.UpdateFace(TopoDS::Face(S),
|
||||
mySurfaces.Surface(s),
|
||||
Locations().Location(l), tol);
|
||||
myBuilder.NaturalRestriction(TopoDS::Face(S), bval);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Compute offset and return back to position before reading surface parameters
|
||||
size_t offset = sizeof(Standard_Integer) * 2 + sizeof(Standard_Real) + sizeof(Standard_Byte);
|
||||
IS.seekg(-offset, IS.cur);
|
||||
}
|
||||
//}
|
||||
Standard_Byte aByte = (Standard_Byte)IS.get();
|
||||
// cas triangulation
|
||||
if(aByte == 2) {
|
||||
|
@@ -95,6 +95,8 @@ Standard_Integer BinTools_SurfaceSet::Add(const Handle(Geom_Surface)& S)
|
||||
Handle(Geom_Surface) BinTools_SurfaceSet::Surface
|
||||
(const Standard_Integer I)const
|
||||
{
|
||||
if (I < 1 || I > myMap.Extent())
|
||||
return Handle(Geom_Surface)();
|
||||
return Handle(Geom_Surface)::DownCast(myMap(I));
|
||||
}
|
||||
|
||||
|
@@ -371,6 +371,22 @@ public:
|
||||
return myZLayers.NbImmediateStructures() != 0;
|
||||
}
|
||||
|
||||
//! Set filter for restricting rendering of particular elements.
|
||||
//! Filter can be applied for rendering passes used by recursive
|
||||
//! rendering algorithms for rendering elements of groups.
|
||||
//! @param theFilter [in] the filter instance.
|
||||
inline void SetRenderFilter(const Handle(OpenGl_RenderFilter)& theFilter)
|
||||
{
|
||||
myWorkspace->SetRenderFilter(theFilter);
|
||||
}
|
||||
|
||||
//! Get rendering filter.
|
||||
//! @return filter instance.
|
||||
inline const Handle(OpenGl_RenderFilter)& GetRenderFilter() const
|
||||
{
|
||||
return myWorkspace->GetRenderFilter();
|
||||
}
|
||||
|
||||
protected: //! @name Internal methods for managing GL resources
|
||||
|
||||
//! Initializes OpenGl resource for environment texture.
|
||||
|
@@ -147,6 +147,8 @@ Standard_Boolean Prs3d_ShapeTool::IsPlanarFace() const
|
||||
TopLoc_Location l;
|
||||
const TopoDS_Face& F = TopoDS::Face(myFaceExplorer.Current());
|
||||
const Handle(Geom_Surface)& S = BRep_Tool::Surface(F, l);
|
||||
if (S.IsNull())
|
||||
return Standard_False;
|
||||
Handle(Standard_Type) TheType = S->DynamicType();
|
||||
|
||||
if (TheType == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
|
||||
|
@@ -41,6 +41,7 @@
|
||||
#include <ShapeFix.hxx>
|
||||
#include <ShapeFix_ComposeShell.hxx>
|
||||
#include <ShapeUpgrade.hxx>
|
||||
#include <ShapeUpgrade_CombineToCylinder.hxx>
|
||||
#include <ShapeUpgrade_RemoveInternalWires.hxx>
|
||||
#include <ShapeUpgrade_RemoveLocations.hxx>
|
||||
#include <ShapeUpgrade_ShapeConvertToBezier.hxx>
|
||||
@@ -1284,14 +1285,16 @@ static ShapeUpgrade_UnifySameDomain& Unifier() {
|
||||
//=======================================================================
|
||||
static Standard_Integer unifysamedom(Draw_Interpretor& di, Standard_Integer n, const char** a)
|
||||
{
|
||||
if (n < 3 || n > 6)
|
||||
if (n < 3)
|
||||
{
|
||||
di << "Use unifysamedom result shape [-f] [-e] [+b] [-i]\n";
|
||||
di << "Use unifysamedom result shape [-f] [-e] [+b] [-i] [-t val] [-a val]\n";
|
||||
di << "options:\n";
|
||||
di << "[-f] to switch off 'unify-faces' mode \n";
|
||||
di << "[-e] to switch off 'unify-edges' mode\n";
|
||||
di << "[+b] to switch on 'concat bspline' mode\n";
|
||||
di << "[+i] to switch on 'allow internal edges' mode\n";
|
||||
di << "-f to switch off 'unify-faces' mode \n";
|
||||
di << "-e to switch off 'unify-edges' mode\n";
|
||||
di << "+b to switch on 'concat bspline' mode\n";
|
||||
di << "+i to switch on 'allow internal edges' mode\n";
|
||||
di << "-t val to set linear tolerance\n";
|
||||
di << "-a val to set angular tolerance\n";
|
||||
di << "'unify-faces' and 'unify-edges' modes are switched on by default";
|
||||
return 1;
|
||||
}
|
||||
@@ -1305,6 +1308,8 @@ static Standard_Integer unifysamedom(Draw_Interpretor& di, Standard_Integer n, c
|
||||
Standard_Boolean anUEdges = Standard_True;
|
||||
Standard_Boolean anConBS = Standard_False;
|
||||
Standard_Boolean isAllowInternal = Standard_False;
|
||||
Standard_Real aLinTol = Precision::Confusion();
|
||||
Standard_Real aAngTol = Precision::Angular();
|
||||
|
||||
if (n > 3)
|
||||
for ( int i = 3; i < n; i++ )
|
||||
@@ -1317,10 +1322,24 @@ static Standard_Integer unifysamedom(Draw_Interpretor& di, Standard_Integer n, c
|
||||
anConBS = Standard_True;
|
||||
else if (!strcmp(a[i], "+i"))
|
||||
isAllowInternal = Standard_True;
|
||||
else if (!strcmp(a[i], "-t") || !strcmp(a[i], "-a"))
|
||||
{
|
||||
if (++i < n)
|
||||
{
|
||||
(a[i-1][1] == 't' ? aLinTol : aAngTol) = Draw::Atof(a[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
di << "value expected after " << a[i-1];
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Unifier().Initialize(aShape, anUEdges, anUFaces, anConBS);
|
||||
Unifier().AllowInternalEdges(isAllowInternal);
|
||||
Unifier().SetLinearTolerance(aLinTol);
|
||||
Unifier().SetAngularTolerance(aAngTol);
|
||||
Unifier().Build();
|
||||
TopoDS_Shape Result = Unifier().Shape();
|
||||
|
||||
@@ -1458,6 +1477,69 @@ Standard_Integer reshape(Draw_Interpretor& di,
|
||||
return 0;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
// CombineToCylinder
|
||||
//=======================================================================
|
||||
static Standard_Integer CombineToCylinder(Draw_Interpretor& di, Standard_Integer n, const char** a)
|
||||
{
|
||||
if (n < 3)
|
||||
{
|
||||
di << "Use combinetocyl result shape [-t val] [-a val]\n";
|
||||
di << "options:\n";
|
||||
di << "-t val to set linear tolerance (default is 1e-7)\n";
|
||||
di << "-a val to set angular tolerance (default is 1e-12)\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
TopoDS_Shape aShape = DBRep::Get(a[2]);
|
||||
if (aShape.IsNull())
|
||||
return 1;
|
||||
|
||||
// default values
|
||||
Standard_Real aLinTol = Precision::Confusion();
|
||||
Standard_Real aAngTol = Precision::Angular();
|
||||
|
||||
if (n > 3)
|
||||
{
|
||||
for (int i = 3; i < n; i++)
|
||||
{
|
||||
if (!strcmp(a[i], "-t") || !strcmp(a[i], "-a"))
|
||||
{
|
||||
if (++i < n)
|
||||
{
|
||||
if (a[i - 1][1] == 't')
|
||||
aLinTol = Draw::Atof(a[i]);
|
||||
else
|
||||
aAngTol = Draw::Atof(a[i]) * M_PI / 180.;
|
||||
}
|
||||
else
|
||||
{
|
||||
di << "value expected after " << a[i - 1];
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ShapeUpgrade_CombineToCylinder aTool;
|
||||
aTool.SetShape(aShape);
|
||||
aTool.SetLinearTolerance(aLinTol);
|
||||
aTool.SetAngularTolerance(aAngTol);
|
||||
aTool.Build();
|
||||
if (!aTool.IsDone())
|
||||
{
|
||||
di << "Not done";
|
||||
}
|
||||
else
|
||||
{
|
||||
di << "Number of new merged faces: " << aTool.NbNewFaces();
|
||||
di << "\nNumber of replaced faces: " << aTool.NbReplacedFaces();
|
||||
const TopoDS_Shape& Result = aTool.Shape();
|
||||
DBRep::Set(a[1], Result);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : InitCommands
|
||||
//purpose :
|
||||
@@ -1556,7 +1638,7 @@ Standard_Integer reshape(Draw_Interpretor& di,
|
||||
theCommands.Add ("removeloc","result shape",__FILE__,removeloc,g);
|
||||
|
||||
theCommands.Add ("unifysamedom",
|
||||
"unifysamedom result shape [-f] [-e] [+b]", __FILE__,unifysamedom,g);
|
||||
"unifysamedom result shape [-f] [-e] [+b] [-i] [-t val] [-a val]", __FILE__,unifysamedom,g);
|
||||
|
||||
theCommands.Add ("unifysamedomgen",
|
||||
"unifysamedomgen newshape oldshape : get new shape generated "
|
||||
@@ -1571,4 +1653,7 @@ Standard_Integer reshape(Draw_Interpretor& di,
|
||||
"\n '-remove what' Removes 'what' sub-shape"
|
||||
"\n Requests '-replace' and '-remove' can be repeated many times.",
|
||||
__FILE__, reshape, g);
|
||||
|
||||
theCommands.Add("combinetocylinder",
|
||||
"run w/o arguments to get help", __FILE__, CombineToCylinder, g);
|
||||
}
|
||||
|
@@ -4,6 +4,8 @@ ShapeUpgrade_ClosedEdgeDivide.cxx
|
||||
ShapeUpgrade_ClosedEdgeDivide.hxx
|
||||
ShapeUpgrade_ClosedFaceDivide.cxx
|
||||
ShapeUpgrade_ClosedFaceDivide.hxx
|
||||
ShapeUpgrade_CombineToCylinder.cxx
|
||||
ShapeUpgrade_CombineToCylinder.hxx
|
||||
ShapeUpgrade_ConvertCurve2dToBezier.cxx
|
||||
ShapeUpgrade_ConvertCurve2dToBezier.hxx
|
||||
ShapeUpgrade_ConvertCurve3dToBezier.cxx
|
||||
|
901
src/ShapeUpgrade/ShapeUpgrade_CombineToCylinder.cxx
Normal file
901
src/ShapeUpgrade/ShapeUpgrade_CombineToCylinder.cxx
Normal file
@@ -0,0 +1,901 @@
|
||||
//-Copyright: Open CASCADE 2016
|
||||
// Created on: 2016-08-01
|
||||
// Created by: Mikhail Sazonov
|
||||
// Copyright (c) 2016 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 <ShapeUpgrade_CombineToCylinder.hxx>
|
||||
#include <BRep_Builder.hxx>
|
||||
#include <BRepAdaptor_Curve.hxx>
|
||||
#include <BRepAdaptor_Surface.hxx>
|
||||
#include <BRepBuilderAPI_MakeEdge.hxx>
|
||||
#include <BRepBuilderAPI_MakeFace.hxx>
|
||||
#include <BRepTools.hxx>
|
||||
#include <BRepTools_ReShape.hxx>
|
||||
#include <ElCLib.hxx>
|
||||
#include <GCPnts_AbscissaPoint.hxx>
|
||||
#include <Geom_Circle.hxx>
|
||||
#include <Geom_BSplineCurve.hxx>
|
||||
#include <GeomAPI_PointsToBSpline.hxx>
|
||||
#include <gce_MakeCirc.hxx>
|
||||
#include <gp_Ax1.hxx>
|
||||
#include <gp_Ax3.hxx>
|
||||
#include <gp_Circ.hxx>
|
||||
#include <gp_Cylinder.hxx>
|
||||
#include <gp_Pln.hxx>
|
||||
#include <IntAna_IntConicQuad.hxx>
|
||||
#include <ShapeAnalysis_Curve.hxx>
|
||||
#include <ShapeFix_Shape.hxx>
|
||||
#include <TColStd_MapOfInteger.hxx>
|
||||
#include <TopoDS.hxx>
|
||||
#include <TopoDS_Compound.hxx>
|
||||
#include <TopoDS_Edge.hxx>
|
||||
#include <TopoDS_Face.hxx>
|
||||
#include <TopExp.hxx>
|
||||
#include <TopExp_Explorer.hxx>
|
||||
#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
|
||||
#include <TopTools_IndexedMapOfShape.hxx>
|
||||
#include <TopTools_MapOfShape.hxx>
|
||||
#include <Precision.hxx>
|
||||
|
||||
//=======================================================================
|
||||
//function : ShapeUpgrade_CombineToCylinder
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
ShapeUpgrade_CombineToCylinder::ShapeUpgrade_CombineToCylinder()
|
||||
: myLinTol(Precision::Confusion()),
|
||||
myAngTol(Precision::Angular()),
|
||||
myNbNewFaces(0),
|
||||
myNbReplacedFaces(0),
|
||||
myDone(Standard_False)
|
||||
{
|
||||
myContext = new BRepTools_ReShape;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : sortEdges
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
static void sortEdges(const TopoDS_Shape& theShape,
|
||||
const TopTools_IndexedDataMapOfShapeListOfShape& theMapEF,
|
||||
const Standard_Real theLinTol,
|
||||
const Standard_Real theAngTol,
|
||||
TopTools_MapOfShape& theStopEdges,
|
||||
NCollection_DataMap<TopoDS_Shape,gp_Cylinder>& theMapECyl)
|
||||
{
|
||||
TopExp_Explorer anEx(theShape, TopAbs_EDGE);
|
||||
for (; anEx.More(); anEx.Next())
|
||||
{
|
||||
const TopoDS_Edge& anEdge = TopoDS::Edge(anEx.Current());
|
||||
const TopTools_ListOfShape* pFaces = theMapEF.Seek(anEdge);
|
||||
if (!pFaces)
|
||||
continue;
|
||||
|
||||
// check for manifold edge
|
||||
if (pFaces->Extent() != 2)
|
||||
{
|
||||
theStopEdges.Add(anEdge);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Get curve of the edge and check if it is a line
|
||||
BRepAdaptor_Curve aCurve(anEdge);
|
||||
if (aCurve.GetType() != GeomAbs_Line)
|
||||
{
|
||||
theStopEdges.Add(anEdge);
|
||||
continue;
|
||||
}
|
||||
// Check if the edge has enough length
|
||||
Standard_Real aLength = GCPnts_AbscissaPoint::Length(aCurve);
|
||||
if (aLength < 2.*theLinTol)
|
||||
{
|
||||
theStopEdges.Add(anEdge);
|
||||
continue;
|
||||
}
|
||||
|
||||
// check that both faces are planar, if no then add the edge to stop list
|
||||
TopoDS_Face aFaces[2] = { TopoDS::Face(pFaces->First()), TopoDS::Face(pFaces->Last()) };
|
||||
BRepAdaptor_Surface aSurf[2] = {
|
||||
BRepAdaptor_Surface(aFaces[0], Standard_False),
|
||||
BRepAdaptor_Surface(aFaces[1], Standard_False) };
|
||||
if (aSurf[0].GetType() != GeomAbs_Plane || aSurf[1].GetType() != GeomAbs_Plane)
|
||||
{
|
||||
theStopEdges.Add(anEdge);
|
||||
continue;
|
||||
}
|
||||
|
||||
// check if edge is sharp, if yes then add it to stop list
|
||||
gp_Pln aPl1 = aSurf[0].Plane();
|
||||
gp_Pln aPl2 = aSurf[1].Plane();
|
||||
if (aPl1.Axis().Direction().Angle(aPl2.Axis().Direction()) > theAngTol)
|
||||
{
|
||||
theStopEdges.Add(anEdge);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Create plane perpendicular to the edge
|
||||
gp_Lin aLin = aCurve.Line();
|
||||
gp_Pln aPln(aLin.Location(), aLin.Direction());
|
||||
|
||||
// Get opposite edges on each face
|
||||
TopoDS_Edge anOpEdges[2];
|
||||
gp_Lin anOpLines[2];
|
||||
Standard_Integer i;
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
TopExp_Explorer anEx1(aFaces[i], TopAbs_EDGE);
|
||||
Standard_Integer nbE = 0;
|
||||
for (; anEx1.More(); anEx1.Next(), nbE++)
|
||||
{
|
||||
if (anOpEdges[i].IsNull())
|
||||
{
|
||||
const TopoDS_Edge& aE = TopoDS::Edge(anEx1.Current());
|
||||
if (!aE.IsSame(anEdge))
|
||||
{
|
||||
BRepAdaptor_Curve aC(aE);
|
||||
if (aC.GetType() == GeomAbs_Line)
|
||||
{
|
||||
gp_Lin aL = aC.Line();
|
||||
if (aL.Direction().IsParallel(aLin.Direction(), theAngTol))
|
||||
{
|
||||
anOpEdges[i] = aE;
|
||||
anOpLines[i] = aL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (nbE != 4)
|
||||
break; // face has non-rectangular form
|
||||
}
|
||||
if (anOpEdges[0].IsNull() || anOpEdges[1].IsNull())
|
||||
{
|
||||
theStopEdges.Add(anEdge);
|
||||
continue;
|
||||
}
|
||||
|
||||
// intersect all 3 edges with the plane
|
||||
gp_Lin aLines[3] = { anOpLines[0], aLin, anOpLines[1] };
|
||||
gp_Pnt anIntPnt[3];
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
IntAna_IntConicQuad anInter(aLines[i], aPln, theAngTol);
|
||||
if (!anInter.IsDone() || anInter.NbPoints() != 1)
|
||||
break;
|
||||
anIntPnt[i] = anInter.Point(1);
|
||||
}
|
||||
if (i < 3)
|
||||
{
|
||||
theStopEdges.Add(anEdge);
|
||||
continue;
|
||||
}
|
||||
|
||||
// check that distances to points on opposite edges are equal
|
||||
Standard_Real aDist1 = anIntPnt[0].Distance(anIntPnt[1]);
|
||||
Standard_Real aDist2 = anIntPnt[2].Distance(anIntPnt[1]);
|
||||
if (fabs(aDist1 - aDist2) > theLinTol)
|
||||
{
|
||||
theStopEdges.Add(anEdge);
|
||||
continue;
|
||||
}
|
||||
|
||||
// compute the circle radius
|
||||
gce_MakeCirc aCircMaker(anIntPnt[0], anIntPnt[1], anIntPnt[2]);
|
||||
if (!aCircMaker.IsDone())
|
||||
{
|
||||
theStopEdges.Add(anEdge);
|
||||
continue;
|
||||
}
|
||||
Standard_Real aRadius = aCircMaker.Value().Radius();
|
||||
const gp_Ax1& aCylAxis = aCircMaker.Value().Axis();
|
||||
gp_Cylinder aCyl(gp_Ax3(aCylAxis.Location(), aCylAxis.Direction()), aRadius);
|
||||
theMapECyl.Bind(anEdge, aCyl);
|
||||
}
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : updateBoundary
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
static void updateBoundary(TopTools_ListOfShape& theBoundary,
|
||||
const TopoDS_Shape& theFace,
|
||||
const TopoDS_Shape& theConnectingEdge,
|
||||
const TopTools_MapOfShape& theStopEdges)
|
||||
{
|
||||
// iterate on all edges of the face
|
||||
TopExp_Explorer anEx(theFace, TopAbs_EDGE);
|
||||
for (; anEx.More(); anEx.Next())
|
||||
{
|
||||
const TopoDS_Edge& anEdge = TopoDS::Edge(anEx.Current());
|
||||
if (anEdge.IsSame(theConnectingEdge) || theStopEdges.Contains(anEdge))
|
||||
continue; // skip stop edges
|
||||
// find this edge in the boundary
|
||||
TopTools_ListIteratorOfListOfShape anIt(theBoundary);
|
||||
while (anIt.More())
|
||||
{
|
||||
if (anIt.Value().IsSame(anEdge))
|
||||
break;
|
||||
anIt.Next();
|
||||
}
|
||||
if (anIt.More())
|
||||
{
|
||||
// found, remove it from boundary
|
||||
theBoundary.Remove(anIt);
|
||||
}
|
||||
else
|
||||
{
|
||||
// not found, add to boundary
|
||||
theBoundary.Append(anEdge);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : Auxiliary structures
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
namespace CombineToCylinder
|
||||
{
|
||||
struct Area
|
||||
{
|
||||
TopoDS_Compound Faces;
|
||||
const gp_Cylinder* pCylinder;
|
||||
Standard_Integer nbFaces;
|
||||
|
||||
Area() : pCylinder(0L), nbFaces(0)
|
||||
{}
|
||||
void Init()
|
||||
{
|
||||
Faces.Nullify();
|
||||
nbFaces = 0;
|
||||
BRep_Builder().MakeCompound(Faces);
|
||||
}
|
||||
void AddFace(const TopoDS_Shape& theFace)
|
||||
{
|
||||
BRep_Builder().Add(Faces, theFace);
|
||||
nbFaces++;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : EqualCylinders
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
inline Standard_Boolean EqualCylinders(const gp_Cylinder& theCyl1,
|
||||
const gp_Cylinder& theCyl2,
|
||||
const Standard_Real theLinTol,
|
||||
const Standard_Real theAngTol)
|
||||
{
|
||||
// check radii
|
||||
if (fabs(theCyl1.Radius() - theCyl2.Radius()) > theLinTol)
|
||||
return Standard_False;
|
||||
// check if parallel
|
||||
if (!theCyl1.Axis().Direction().IsParallel(theCyl2.Axis().Direction(), theAngTol))
|
||||
return Standard_False;
|
||||
// check distance between axes
|
||||
gp_XYZ aVecO1O2 = theCyl2.Location().XYZ() - theCyl1.Location().XYZ();
|
||||
Standard_Real aDist1 = aVecO1O2.CrossSquareMagnitude(theCyl2.Axis().Direction().XYZ());
|
||||
Standard_Real aDist2 = aVecO1O2.CrossSquareMagnitude(theCyl1.Axis().Direction().XYZ());
|
||||
Standard_Real aTol = theLinTol * theLinTol;
|
||||
return aDist1 <= aTol && aDist2 < aTol;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : collectAreas
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
static void collectAreas(const TopoDS_Shape& theShape,
|
||||
const TopTools_IndexedDataMapOfShapeListOfShape& theMapEF,
|
||||
const TopTools_MapOfShape& theStopEdges,
|
||||
const NCollection_DataMap<TopoDS_Shape, gp_Cylinder>& theMapECyl,
|
||||
const Standard_Real theLinTol,
|
||||
const Standard_Real theAngTol,
|
||||
NCollection_List<CombineToCylinder::Area>& theAreas)
|
||||
{
|
||||
TopTools_MapOfShape aPassedFaces;
|
||||
|
||||
// Repeat while there are unprocessed faces
|
||||
for (;;)
|
||||
{
|
||||
// get first unprocessed face
|
||||
TopoDS_Shape aCurFace;
|
||||
TopExp_Explorer anEx(theShape, TopAbs_FACE);
|
||||
for (; anEx.More(); anEx.Next())
|
||||
{
|
||||
aCurFace = anEx.Current();
|
||||
if (!aPassedFaces.Contains(aCurFace))
|
||||
break;
|
||||
}
|
||||
if (!anEx.More())
|
||||
break; // all are processed, stop
|
||||
|
||||
// Start area with it
|
||||
CombineToCylinder::Area anArea;
|
||||
anArea.Init();
|
||||
anArea.AddFace(aCurFace);
|
||||
aPassedFaces.Add(aCurFace);
|
||||
|
||||
// Define edges of boundary of area
|
||||
TopTools_ListOfShape aBoundary;
|
||||
updateBoundary(aBoundary, aCurFace, TopoDS_Shape(), theStopEdges);
|
||||
|
||||
// Add all neighbors to the area while there are unprocessed edges of boundary
|
||||
while (!aBoundary.IsEmpty())
|
||||
{
|
||||
TopTools_ListIteratorOfListOfShape anIt(aBoundary);
|
||||
while (anIt.More())
|
||||
{
|
||||
const TopoDS_Shape& anEdge = anIt.Value();
|
||||
const gp_Cylinder* pCyl = theMapECyl.Seek(anEdge);
|
||||
const TopTools_ListOfShape* pFaces = theMapEF.Seek(anEdge);
|
||||
Standard_ASSERT_RAISE(pCyl && pFaces && pFaces->Extent() == 2, "collectAreas");
|
||||
if (!anArea.pCylinder || EqualCylinders(*anArea.pCylinder, *pCyl, theLinTol, theAngTol))
|
||||
{
|
||||
anArea.pCylinder = pCyl;
|
||||
aCurFace = (aPassedFaces.Contains(pFaces->First()) ? pFaces->Last() : pFaces->First());
|
||||
if (!aPassedFaces.Contains(aCurFace))
|
||||
{
|
||||
// Update boundary adding the next face
|
||||
updateBoundary(aBoundary, aCurFace, anEdge, theStopEdges);
|
||||
anArea.AddFace(aCurFace);
|
||||
aPassedFaces.Add(aCurFace);
|
||||
}
|
||||
}
|
||||
aBoundary.Remove(anIt);
|
||||
}
|
||||
}
|
||||
|
||||
// check if area is well formed
|
||||
if (anArea.pCylinder && anArea.nbFaces > 2)
|
||||
{
|
||||
// Add area to the result list
|
||||
theAreas.Append(anArea);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : getNextEdge
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
static Standard_Boolean getNextEdge(const TopTools_ListOfShape& theChain,
|
||||
const Standard_Boolean theFwd,
|
||||
const TopTools_IndexedDataMapOfShapeListOfShape& theMapVE,
|
||||
const Standard_Real theSmoothAng,
|
||||
TopoDS_Edge& theNextEdge)
|
||||
{
|
||||
// Get end edge and vertex
|
||||
TopoDS_Edge anEndE, anOppoEdge;
|
||||
TopoDS_Vertex anEndV;
|
||||
if (theFwd)
|
||||
{
|
||||
anEndE = TopoDS::Edge(theChain.Last());
|
||||
anOppoEdge = TopoDS::Edge(theChain.First());
|
||||
anEndV = TopExp::LastVertex(anEndE, Standard_True);
|
||||
}
|
||||
else
|
||||
{
|
||||
anEndE = TopoDS::Edge(theChain.First());
|
||||
anOppoEdge = TopoDS::Edge(theChain.Last());
|
||||
anEndV = TopExp::FirstVertex(anEndE, Standard_True);
|
||||
}
|
||||
|
||||
// Get next edge using topology map; reject the case of multi-connected vertex,
|
||||
// when there are more than one candidate edge
|
||||
const TopTools_ListOfShape& aConnEdges = theMapVE.FindFromKey(anEndV);
|
||||
// Note! aConnEdges can contain duplicates
|
||||
theNextEdge.Nullify();
|
||||
TopTools_ListIteratorOfListOfShape itL(aConnEdges);
|
||||
for (; itL.More(); itL.Next())
|
||||
{
|
||||
const TopoDS_Shape& aE = itL.Value();
|
||||
if (aE.IsSame(anEndE))
|
||||
continue;
|
||||
if (theNextEdge.IsNull())
|
||||
theNextEdge = TopoDS::Edge(aE);
|
||||
else if(!aE.IsSame(theNextEdge))
|
||||
return Standard_False; // multi-connected vertex
|
||||
}
|
||||
|
||||
// check for closed chain
|
||||
if (theNextEdge.IsSame(anOppoEdge))
|
||||
return Standard_False;
|
||||
|
||||
// Orient the next edge
|
||||
TopoDS_Vertex aNextEndV = (theFwd ? TopExp::FirstVertex(theNextEdge, Standard_True) :
|
||||
TopExp::LastVertex(theNextEdge, Standard_True));
|
||||
if (!aNextEndV.IsSame(anEndV))
|
||||
theNextEdge.Reverse();
|
||||
|
||||
if (theSmoothAng > 0.)
|
||||
{
|
||||
// Check that the edge is linear
|
||||
BRepAdaptor_Curve aNextC(theNextEdge);
|
||||
if (aNextC.GetType() != GeomAbs_Line)
|
||||
return Standard_False;
|
||||
|
||||
// Verify smoothness of connection
|
||||
BRepAdaptor_Curve anEndC(anEndE);
|
||||
gp_Lin anEndLin = anEndC.Line();
|
||||
gp_Lin aNextLin = aNextC.Line();
|
||||
const gp_Dir& anEndDir = anEndLin.Direction();
|
||||
const gp_Dir& aNextDir = aNextLin.Direction();
|
||||
if (!anEndDir.IsParallel(aNextDir, theSmoothAng))
|
||||
return Standard_False;
|
||||
}
|
||||
return Standard_True;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : makeEdgesChain
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
static void makeEdgesChain(TopTools_ListOfShape& theChain,
|
||||
const TopTools_IndexedDataMapOfShapeListOfShape& theMapVE,
|
||||
const Standard_Real theSmoothAng)
|
||||
{
|
||||
// Cycle for both ends of the chain
|
||||
Standard_Boolean isFwd[2] = { Standard_True, Standard_False };
|
||||
for (Standard_Integer i = 0; i < 2; i++)
|
||||
{
|
||||
TopoDS_Edge aNextEdge;
|
||||
while (getNextEdge(theChain, isFwd[i], theMapVE, theSmoothAng, aNextEdge))
|
||||
{
|
||||
// add next edge to the chain
|
||||
if (isFwd[i])
|
||||
theChain.Append(aNextEdge);
|
||||
else
|
||||
theChain.Prepend(aNextEdge);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : createCylFaceFromArea
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
static TopoDS_Face createCylFaceFromArea(const TopoDS_Compound& theFaces,
|
||||
const gp_Cylinder& theCylinder)
|
||||
{
|
||||
// Find boundary edges of the area
|
||||
TopTools_IndexedDataMapOfShapeListOfShape aMapEF, aMapVE;
|
||||
TopExp::MapShapesAndAncestors(theFaces, TopAbs_EDGE, TopAbs_FACE, aMapEF);
|
||||
TopTools_ListOfShape aBoundary;
|
||||
Standard_Integer i;
|
||||
for (i = 1; i <= aMapEF.Extent(); i++)
|
||||
{
|
||||
if (aMapEF(i).Extent() == 1)
|
||||
{
|
||||
const TopoDS_Shape& aE = aMapEF.FindKey(i);
|
||||
aBoundary.Append(aE);
|
||||
TopExp::MapShapesAndAncestors(aE, TopAbs_VERTEX, TopAbs_EDGE, aMapVE);
|
||||
}
|
||||
}
|
||||
|
||||
// Check the case of closed cylinder. In this case there will be two
|
||||
// distinct chains of boundary edges, and we need to create a seam edge
|
||||
TopoDS_Edge aSeamEdge;
|
||||
TopTools_ListOfShape aChain;
|
||||
aChain.Append(aBoundary.First());
|
||||
makeEdgesChain(aChain, aMapVE, 0.);
|
||||
TopTools_MapOfShape aMapChain;
|
||||
TopTools_ListIteratorOfListOfShape itC(aChain);
|
||||
for (; itC.More(); itC.Next())
|
||||
aMapChain.Add(itC.Value());
|
||||
TopTools_ListIteratorOfListOfShape itB(aBoundary);
|
||||
for (; itB.More(); itB.Next())
|
||||
{
|
||||
if (!aMapChain.Contains(itB.Value()))
|
||||
break;
|
||||
}
|
||||
if (itB.More())
|
||||
{
|
||||
// It is the case.
|
||||
// Get any multi-connected edge and use it as a seam
|
||||
for (i = 1; i <= aMapEF.Extent(); i++)
|
||||
if (aMapEF(i).Extent() == 2)
|
||||
aSeamEdge = TopoDS::Edge(aMapEF.FindKey(i));
|
||||
}
|
||||
|
||||
// Build new cylindrical face
|
||||
TopoDS_Wire aWire;
|
||||
BRep_Builder().MakeWire(aWire);
|
||||
for (itB.Init(aBoundary); itB.More(); itB.Next())
|
||||
{
|
||||
BRep_Builder().Add(aWire, itB.Value());
|
||||
}
|
||||
if (!aSeamEdge.IsNull())
|
||||
{
|
||||
BRep_Builder().Add(aWire, aSeamEdge);
|
||||
BRep_Builder().Add(aWire, aSeamEdge.Reversed());
|
||||
}
|
||||
TopoDS_Face aCylFace = BRepBuilderAPI_MakeFace(theCylinder, aWire);
|
||||
|
||||
// Check orientation of an initial face, so that possibly to reverse the new face.
|
||||
// The new cylindrical surface always has normal directed outside of cylinder.
|
||||
// If an initial face has normal (taking face orientation into account) directed
|
||||
// inside then we must reverse the new face.
|
||||
const TopoDS_Edge& aE = TopoDS::Edge(aBoundary.First());
|
||||
const TopoDS_Face& aF = TopoDS::Face(aMapEF.FindFromKey(aE).First());
|
||||
BRepAdaptor_Surface aSurf(aF, Standard_False);
|
||||
Standard_Real aParF, aParL;
|
||||
Handle(Geom2d_Curve) aPCurve = BRep_Tool::CurveOnSurface(aE, aF, aParF, aParL);
|
||||
Standard_ASSERT_RAISE(!aPCurve.IsNull(), "createCylFaceFromArea");
|
||||
gp_Pnt2d aP2d = aPCurve->Value(aParF);
|
||||
gp_Pnt aP;
|
||||
gp_Vec aDU, aDV;
|
||||
aSurf.D1(aP2d.X(), aP2d.Y(), aP, aDU, aDV);
|
||||
gp_XYZ aN = aDU.XYZ() ^ aDV.XYZ();
|
||||
if (aF.Orientation() == TopAbs_REVERSED)
|
||||
aN.Reverse();
|
||||
gp_XYZ aVecFromAxis = aP.XYZ() - theCylinder.Location().XYZ();
|
||||
if (aVecFromAxis * aN < 0.)
|
||||
{
|
||||
// need reverse
|
||||
aCylFace.Reverse();
|
||||
}
|
||||
return aCylFace;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : updateVertexOnCirc
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
static Standard_Boolean updateVertexOnCirc(const TopoDS_Vertex& theV,
|
||||
const gp_Circ& theCirc,
|
||||
Standard_Real theMaxDist,
|
||||
Standard_Real& thePar)
|
||||
{
|
||||
Standard_Real aTol = BRep_Tool::Tolerance(theV);
|
||||
gp_Pnt aP = BRep_Tool::Pnt(theV);
|
||||
thePar = ElCLib::Parameter(theCirc, aP);
|
||||
gp_Pnt aProj = ElCLib::Value(thePar, theCirc);
|
||||
Standard_Real aDist = aProj.SquareDistance(aP);
|
||||
Standard_Boolean isOK = Standard_False;
|
||||
if (aDist > aTol*aTol)
|
||||
{
|
||||
if (aDist < theMaxDist*theMaxDist)
|
||||
{
|
||||
BRep_Builder().UpdateVertex(theV, sqrt(aDist)*1.001);
|
||||
isOK = Standard_True;
|
||||
}
|
||||
}
|
||||
return isOK;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : createCurveEdge
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
static TopoDS_Edge createCurveEdge(const TopTools_ListOfShape& theChain,
|
||||
const TopTools_IndexedDataMapOfShapeListOfShape& theMapEF,
|
||||
const Standard_Real theLinTol)
|
||||
{
|
||||
// Find a cylindrical face common for all edges
|
||||
TopTools_ListOfShape aCylFaces;
|
||||
TopTools_ListIteratorOfListOfShape itL(theChain);
|
||||
for (; itL.More(); itL.Next())
|
||||
{
|
||||
const TopoDS_Shape& aE = itL.Value();
|
||||
const TopTools_ListOfShape& aFaces = theMapEF.FindFromKey(aE);
|
||||
// get cyl faces of the current edge
|
||||
TopTools_ListOfShape aCurCylFaces;
|
||||
TopTools_ListIteratorOfListOfShape itF(aFaces);
|
||||
for (; itF.More(); itF.Next())
|
||||
{
|
||||
const TopoDS_Face& aF = TopoDS::Face(itF.Value());
|
||||
BRepAdaptor_Surface aSurf(aF, Standard_False);
|
||||
if (aSurf.GetType() == GeomAbs_Cylinder)
|
||||
aCurCylFaces.Append(aF);
|
||||
}
|
||||
|
||||
if (aCylFaces.IsEmpty())
|
||||
// initialize cyl faces with the first edge
|
||||
aCylFaces.Append(aCurCylFaces);
|
||||
else
|
||||
{
|
||||
// filter cyl faces leaving only common ones
|
||||
TopTools_ListIteratorOfListOfShape itCF(aCylFaces);
|
||||
while (itCF.More())
|
||||
{
|
||||
const TopoDS_Shape& aF = itCF.Value();
|
||||
TopTools_ListIteratorOfListOfShape itCF1(aCurCylFaces);
|
||||
for (; itCF1.More(); itCF1.Next())
|
||||
if (itCF1.Value().IsSame(aF))
|
||||
break;
|
||||
if (!itCF1.More())
|
||||
aCylFaces.Remove(itCF);
|
||||
else
|
||||
itCF.Next();
|
||||
}
|
||||
}
|
||||
if (aCylFaces.IsEmpty())
|
||||
return TopoDS_Edge(); // no common cyl faces
|
||||
}
|
||||
if (aCylFaces.IsEmpty())
|
||||
return TopoDS_Edge();
|
||||
const TopoDS_Face& aCylFace = TopoDS::Face(aCylFaces.First());
|
||||
BRepAdaptor_Surface aCylSurf(aCylFace, Standard_False);
|
||||
gp_Cylinder aCyl = aCylSurf.Cylinder();
|
||||
const gp_Dir& aCylDir = aCyl.Axis().Direction();
|
||||
const gp_Pnt& aCylLoc = aCyl.Location();
|
||||
const Standard_Real aRadius = aCyl.Radius();
|
||||
|
||||
// Check if the chain is closed
|
||||
TopoDS_Vertex aVF, aVL;
|
||||
aVF = TopoDS::Vertex(TopExp::FirstVertex(TopoDS::Edge(theChain.First()), Standard_True));
|
||||
aVL = TopoDS::Vertex(TopExp::LastVertex(TopoDS::Edge(theChain.Last()), Standard_True));
|
||||
Standard_Boolean isClosed = aVF.IsSame(aVL);
|
||||
|
||||
// Check if all points are in plane perpendicular to the cylinder axis;
|
||||
// in such case the curve is a circle
|
||||
TColgp_Array1OfPnt aPnts(1, theChain.Extent()+1);
|
||||
Standard_Real aTol = 0.;
|
||||
Standard_Integer i = 1;
|
||||
for (itL.Init(theChain); itL.More(); itL.Next(), i++)
|
||||
{
|
||||
const TopoDS_Edge& aE = TopoDS::Edge(itL.Value());
|
||||
TopoDS_Shape aV = TopExp::FirstVertex(aE, Standard_True);
|
||||
aPnts(i) = BRep_Tool::Pnt(TopoDS::Vertex(aV));
|
||||
aTol = Max(aTol, BRep_Tool::Tolerance(aE));
|
||||
}
|
||||
aPnts(i) = BRep_Tool::Pnt(aVL);
|
||||
gp_XYZ aMidPnt(0, 0, 0);
|
||||
for (i = 1; i <= aPnts.Length(); i++)
|
||||
aMidPnt += aPnts(i).XYZ();
|
||||
aMidPnt /= aPnts.Length();
|
||||
aTol = Min(aTol, theLinTol);
|
||||
for (i = 1; i <= aPnts.Length(); i++)
|
||||
{
|
||||
Standard_Real aDist = fabs((aPnts(i).XYZ() - aMidPnt) * aCylDir.XYZ());
|
||||
if (aDist > aTol)
|
||||
break;
|
||||
}
|
||||
Standard_Boolean isCircle = (i > aPnts.Length());
|
||||
|
||||
// Create new edge
|
||||
TopoDS_Edge aNewEdge;
|
||||
if (isCircle)
|
||||
{
|
||||
// Create circular edge.
|
||||
// Find center by projecting aMidPnt to the cylinder axis
|
||||
gp_XYZ aVecOM = aMidPnt - aCylLoc.XYZ();
|
||||
gp_Pnt aCenter = aCylLoc.Translated(aCylDir.XYZ() * (aVecOM * aCylDir.XYZ()));
|
||||
gp_XYZ aXDir = aPnts(1).XYZ() - aCenter.XYZ();
|
||||
gp_XYZ aCircDir = aCylDir.XYZ();
|
||||
gp_XYZ aTanDir = aPnts(2).XYZ() - aPnts(1).XYZ();
|
||||
if ((aXDir ^ aTanDir)* aCylDir.XYZ() < 0.)
|
||||
aCircDir.Reverse();
|
||||
gp_Circ aCirc(gp_Ax2(aCenter, aCircDir, aXDir), aRadius);
|
||||
Handle(Geom_Circle) aCurve = new Geom_Circle(aCirc);
|
||||
// update vertices tolerance, but not more than on a value aTol,
|
||||
// otherwise skip building a circle, and build bspline.
|
||||
Standard_Real aPar;
|
||||
if (updateVertexOnCirc(aVF, aCirc, aTol, aPar))
|
||||
{
|
||||
if (isClosed)
|
||||
{
|
||||
// full circle
|
||||
aNewEdge = BRepBuilderAPI_MakeEdge(aCurve, aVF, aVL, 0, M_PI*2.);
|
||||
}
|
||||
else
|
||||
{
|
||||
// an arc
|
||||
if (updateVertexOnCirc(aVL, aCirc, aTol, aPar))
|
||||
aNewEdge = BRepBuilderAPI_MakeEdge(aCurve, aVF, aVL, 0., aPar);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (aNewEdge.IsNull())
|
||||
{
|
||||
// not a circle, try building bspline
|
||||
gp_Pnt aPnts1[3];
|
||||
const gp_Pnt* pPnts = &aPnts(1);
|
||||
Standard_Integer np = aPnts.Length();
|
||||
if (np == 2)
|
||||
{
|
||||
gp_XYZ anEdgeDir = aPnts(2).XYZ() - aPnts(1).XYZ();
|
||||
const Standard_Real anEpsAng = 1e-4;
|
||||
if (aCylDir.IsParallel(anEdgeDir, anEpsAng))
|
||||
return aNewEdge;
|
||||
// we have only two points; create additional point in the middle of the segment
|
||||
aPnts1[0] = aPnts(1);
|
||||
aPnts1[2] = aPnts(2);
|
||||
aPnts1[1] = (aPnts1[0].XYZ() + aPnts1[2].XYZ()) * 0.5;
|
||||
pPnts = aPnts1;
|
||||
np = 3;
|
||||
}
|
||||
TColgp_Array1OfPnt aPntA(*pPnts, 1, np);
|
||||
// Create b-spline curve
|
||||
Standard_Integer aDegMin = 3;
|
||||
Standard_Integer aDegMax = 3;
|
||||
GeomAbs_Shape aCont = GeomAbs_C2;
|
||||
GeomAPI_PointsToBSpline aCreator(aPntA, aDegMin, aDegMax, aCont, aTol);
|
||||
if (aCreator.IsDone())
|
||||
{
|
||||
const Handle(Geom_BSplineCurve)& aCurve = aCreator.Curve();
|
||||
Standard_Real aTol = BRep_Tool::Tolerance(aVF);
|
||||
Standard_Real aParF = aCurve->FirstParameter();
|
||||
Standard_Real aParL = aCurve->LastParameter();
|
||||
Standard_Real aDist = aCurve->Value(aParF).SquareDistance(aPntA(1));
|
||||
if (aDist > aTol*aTol)
|
||||
BRep_Builder().UpdateVertex(aVF, sqrt(aDist));
|
||||
if (!isClosed)
|
||||
{
|
||||
aTol = BRep_Tool::Tolerance(aVL);
|
||||
aDist = aCurve->Value(aParL).SquareDistance(aPntA(np));
|
||||
if (aDist > aTol*aTol)
|
||||
BRep_Builder().UpdateVertex(aVL, sqrt(aDist));
|
||||
}
|
||||
aNewEdge = BRepBuilderAPI_MakeEdge(aCurve, aVF, aVL, aParF, aParL);
|
||||
}
|
||||
}
|
||||
return aNewEdge;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : mergeEdges
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
static void mergeEdges(const TopoDS_Shape& theShape,
|
||||
const Standard_Real theLinTol,
|
||||
const Standard_Real theAngTol,
|
||||
const Handle(BRepTools_ReShape)& theContext)
|
||||
{
|
||||
// Create topological data maps
|
||||
TopTools_IndexedDataMapOfShapeListOfShape aMapVE, aMapEF;
|
||||
TopExp::MapShapesAndAncestors(theShape, TopAbs_VERTEX, TopAbs_EDGE, aMapVE);
|
||||
TopExp::MapShapesAndAncestors(theShape, TopAbs_EDGE, TopAbs_FACE, aMapEF);
|
||||
|
||||
// The idea is to gather chains of edges in which all intermediate vertices
|
||||
// have only two neighboring edges, and do not have connection to any other edges
|
||||
// from the shape.
|
||||
|
||||
// Prepare set of all edges
|
||||
TopTools_IndexedMapOfShape anEdges;
|
||||
TopExp::MapShapes(theShape, TopAbs_EDGE, anEdges);
|
||||
TColStd_MapOfInteger anEdgesInd; // set of indices of left edges
|
||||
Standard_Integer i;
|
||||
for (i = 1; i <= anEdges.Extent(); i++)
|
||||
anEdgesInd.Add(i);
|
||||
|
||||
// Process while there are unprocessed edges
|
||||
while (!anEdgesInd.IsEmpty())
|
||||
{
|
||||
// Get an unprocessed edge
|
||||
Standard_Integer aEInd = TColStd_MapIteratorOfMapOfInteger(anEdgesInd).Value();
|
||||
anEdgesInd.Remove(aEInd);
|
||||
TopoDS_Edge aFirstEdge = TopoDS::Edge(anEdges(aEInd));
|
||||
BRepAdaptor_Curve aCurve(aFirstEdge);
|
||||
if (aCurve.GetType() != GeomAbs_Line)
|
||||
continue; // only linear edges are to be merged
|
||||
|
||||
// Start a new chain
|
||||
TopTools_ListOfShape aChain;
|
||||
aChain.Append(aFirstEdge.Oriented(TopAbs_FORWARD));
|
||||
makeEdgesChain(aChain, aMapVE, theAngTol);
|
||||
|
||||
// Remove it from the left edges
|
||||
TopTools_ListIteratorOfListOfShape itL(aChain);
|
||||
for (; itL.More(); itL.Next())
|
||||
{
|
||||
const TopoDS_Shape& aE = itL.Value();
|
||||
Standard_Integer aEI = anEdges.FindIndex(aE);
|
||||
anEdgesInd.Remove(aEI);
|
||||
}
|
||||
|
||||
if (aChain.Extent() > 0)
|
||||
{
|
||||
// Create a new curvilinear edge from the polyline
|
||||
TopoDS_Edge aNewEdge = createCurveEdge(aChain, aMapEF, theLinTol);
|
||||
if (!aNewEdge.IsNull())
|
||||
{
|
||||
aNewEdge.Orientation(aFirstEdge.Orientation());
|
||||
// Replace edges from the chain with the new edge.
|
||||
Standard_Integer nbMerged = 0;
|
||||
for (itL.Init(aChain); itL.More(); itL.Next(), nbMerged++)
|
||||
{
|
||||
const TopoDS_Shape& aE = itL.Value();
|
||||
if (nbMerged == 0)
|
||||
theContext->Replace(aE, aNewEdge);
|
||||
else
|
||||
theContext->Remove(aE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : Build
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
void ShapeUpgrade_CombineToCylinder::Build()
|
||||
{
|
||||
myDone = Standard_False;
|
||||
myNbNewFaces = myNbReplacedFaces = 0;
|
||||
myShape.Nullify();
|
||||
|
||||
TopTools_IndexedDataMapOfShapeListOfShape aMapEF;
|
||||
TopExp::MapShapesAndAncestors(myInitShape, TopAbs_EDGE, TopAbs_FACE, aMapEF);
|
||||
|
||||
// Sort edges in the shape on two groups - stop edges and smooth edges that are
|
||||
// to be located on a cylinder wall parallel to its axis.
|
||||
TopTools_MapOfShape aStopEdges;
|
||||
NCollection_DataMap<TopoDS_Shape, gp_Cylinder> aMapECyl;
|
||||
sortEdges(myInitShape, aMapEF, myLinTol, myAngTol, aStopEdges, aMapECyl);
|
||||
|
||||
#ifdef DEBUG_CombineToCylinder_StopEdges
|
||||
TopoDS_Compound aCompE;
|
||||
BRep_Builder().MakeCompound(aCompE);
|
||||
TopTools_MapIteratorOfMapOfShape aMapIt(aStopEdges);
|
||||
for (; aMapIt.More(); aMapIt.Next())
|
||||
BRep_Builder().Add(aCompE, aMapIt.Value());
|
||||
BRepTools::Write(aCompE, "stope.brep");
|
||||
#endif
|
||||
|
||||
// Collect faces forming same-cylinder areas
|
||||
NCollection_List<CombineToCylinder::Area> anAreas;
|
||||
collectAreas(myInitShape, aMapEF, aStopEdges, aMapECyl, myLinTol, myAngTol, anAreas);
|
||||
|
||||
#ifdef DEBUG_CombineToCylinder_Areas
|
||||
TopoDS_Compound aComp;
|
||||
BRep_Builder().MakeCompound(aComp);
|
||||
TopTools_ListIteratorOfListOfShape anItA(anAreas);
|
||||
for (; anItA.More(); anItA.Next())
|
||||
BRep_Builder().Add(aComp, anItA.Value());
|
||||
BRepTools::Write(aComp, "areas.brep");
|
||||
#endif
|
||||
|
||||
// Process each area
|
||||
NCollection_List<CombineToCylinder::Area>::Iterator anItAreas(anAreas);
|
||||
for (; anItAreas.More(); anItAreas.Next())
|
||||
{
|
||||
const CombineToCylinder::Area& anArea = anItAreas.Value();
|
||||
if (!anArea.pCylinder)
|
||||
continue;
|
||||
|
||||
TopoDS_Shape aCylFace = createCylFaceFromArea(anArea.Faces, *anArea.pCylinder);
|
||||
|
||||
// Replace faces from the list with the new face.
|
||||
TopExp_Explorer anEx(anArea.Faces, TopAbs_FACE);
|
||||
Standard_Integer nbMerged = 0;
|
||||
for (; anEx.More(); anEx.Next(), nbMerged++)
|
||||
{
|
||||
const TopoDS_Shape& aFace = anEx.Current();
|
||||
if (nbMerged == 0)
|
||||
myContext->Replace(aFace, aCylFace);
|
||||
else
|
||||
myContext->Remove(aFace);
|
||||
}
|
||||
myNbNewFaces++;
|
||||
myNbReplacedFaces += nbMerged;
|
||||
}
|
||||
|
||||
// Build intermediate result shape using replacement context.
|
||||
// This shape will contain chains of linear edges along cylinders
|
||||
// instead of circles or whatever curves.
|
||||
// The next step is to merge them.
|
||||
TopoDS_Shape aTempShape = myContext->Apply(myInitShape);
|
||||
mergeEdges(aTempShape, myLinTol, myAngTol, myContext);
|
||||
|
||||
// Rebuild the result shape using replacement context.
|
||||
myShape = myContext->Apply(myInitShape);
|
||||
|
||||
// build pcurves
|
||||
ShapeFix_Shape aFix(myShape);
|
||||
aFix.Perform();
|
||||
myShape = aFix.Shape();
|
||||
myDone = Standard_True;
|
||||
}
|
93
src/ShapeUpgrade/ShapeUpgrade_CombineToCylinder.hxx
Normal file
93
src/ShapeUpgrade/ShapeUpgrade_CombineToCylinder.hxx
Normal file
@@ -0,0 +1,93 @@
|
||||
//-Copyright: Open CASCADE 2016
|
||||
// Created on: 2016-08-01
|
||||
// Created by: Mikhail Sazonov
|
||||
// Copyright (c) 2016 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.
|
||||
|
||||
#ifndef _ShapeUpgrade_CombineToCylinder_HeaderFile
|
||||
#define _ShapeUpgrade_CombineToCylinder_HeaderFile
|
||||
|
||||
#include <Standard_TypeDef.hxx>
|
||||
#include <TopoDS_Shape.hxx>
|
||||
|
||||
class BRepTools_ReShape;
|
||||
|
||||
//! This tool tries to merge planar faces constituting a cylindrical surface into one face.
|
||||
//! The algorithm checks that all merged faces have smooth change of normal within the given
|
||||
//! angular tolerance.
|
||||
class ShapeUpgrade_CombineToCylinder
|
||||
{
|
||||
public:
|
||||
|
||||
//! empty constructor
|
||||
Standard_EXPORT ShapeUpgrade_CombineToCylinder();
|
||||
|
||||
//! Sets input shape
|
||||
void SetShape(const TopoDS_Shape& theShape)
|
||||
{
|
||||
myInitShape = theShape;
|
||||
}
|
||||
|
||||
//! Sets the linear tolerance. Default value is Precision::Confusion().
|
||||
void SetLinearTolerance(const Standard_Real theValue)
|
||||
{
|
||||
myLinTol = theValue;
|
||||
}
|
||||
|
||||
//! Sets the angular tolerance. Default value is Precision::Angular().
|
||||
void SetAngularTolerance(const Standard_Real theValue)
|
||||
{
|
||||
myAngTol = theValue;
|
||||
}
|
||||
|
||||
//! Builds the resulting shape
|
||||
Standard_EXPORT void Build();
|
||||
|
||||
//! Returns true if the result shape was successfully built.
|
||||
Standard_Boolean IsDone() const
|
||||
{
|
||||
return myDone;
|
||||
}
|
||||
|
||||
//! Returns the result shape.
|
||||
const TopoDS_Shape& Shape() const
|
||||
{
|
||||
return myShape;
|
||||
}
|
||||
|
||||
//! Returns the number of new faces built by merging
|
||||
Standard_Integer NbNewFaces() const
|
||||
{
|
||||
return myNbNewFaces;
|
||||
}
|
||||
|
||||
//! Returns the number of replaced faces
|
||||
Standard_Integer NbReplacedFaces() const
|
||||
{
|
||||
return myNbReplacedFaces;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
TopoDS_Shape myInitShape;
|
||||
Standard_Real myLinTol;
|
||||
Standard_Real myAngTol;
|
||||
TopoDS_Shape myShape;
|
||||
Handle(BRepTools_ReShape) myContext;
|
||||
Standard_Integer myNbNewFaces;
|
||||
Standard_Integer myNbReplacedFaces;
|
||||
Standard_Boolean myDone;
|
||||
|
||||
};
|
||||
|
||||
#endif // _ShapeUpgrade_CombineToCylinder_HeaderFile
|
@@ -306,7 +306,9 @@ static Handle(Geom_Surface) ClearRts(const Handle(Geom_Surface)& aSurface)
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
static Standard_Boolean IsSameDomain(const TopoDS_Face& aFace,
|
||||
const TopoDS_Face& aCheckedFace)
|
||||
const TopoDS_Face& aCheckedFace,
|
||||
const Standard_Real theLinTol,
|
||||
const Standard_Real theAngTol)
|
||||
{
|
||||
//checking the same handles
|
||||
TopLoc_Location L1, L2;
|
||||
@@ -318,9 +320,6 @@ static Standard_Boolean IsSameDomain(const TopoDS_Face& aFace,
|
||||
if (S1 == S2 && L1 == L2)
|
||||
return Standard_True;
|
||||
|
||||
// planar and cylindrical cases (IMP 20052)
|
||||
Standard_Real aPrec = Precision::Confusion();
|
||||
|
||||
S1 = BRep_Tool::Surface(aFace);
|
||||
S2 = BRep_Tool::Surface(aCheckedFace);
|
||||
|
||||
@@ -333,6 +332,22 @@ static Standard_Boolean IsSameDomain(const TopoDS_Face& aFace,
|
||||
//if (!aGOFS1.IsNull()) S1 = aGOFS1->BasisSurface();
|
||||
//if (!aGOFS2.IsNull()) S2 = aGOFS2->BasisSurface();
|
||||
|
||||
// case of two planar surfaces:
|
||||
// all kinds of surfaces checked, including b-spline and bezier
|
||||
GeomLib_IsPlanarSurface aPlanarityChecker1(S1, theLinTol);
|
||||
if (aPlanarityChecker1.IsPlanar()) {
|
||||
GeomLib_IsPlanarSurface aPlanarityChecker2(S2, theLinTol);
|
||||
if (aPlanarityChecker2.IsPlanar()) {
|
||||
gp_Pln aPln1 = aPlanarityChecker1.Plan();
|
||||
gp_Pln aPln2 = aPlanarityChecker2.Plan();
|
||||
|
||||
if (aPln1.Position().Direction().IsParallel(aPln2.Position().Direction(), theAngTol) &&
|
||||
aPln1.Distance(aPln2) < theLinTol) {
|
||||
return Standard_True;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// case of two elementary surfaces: use OCCT tool
|
||||
// elementary surfaces: ConicalSurface, CylindricalSurface,
|
||||
// Plane, SphericalSurface and ToroidalSurface
|
||||
@@ -346,7 +361,7 @@ static Standard_Boolean IsSameDomain(const TopoDS_Face& aFace,
|
||||
Handle(BRepTopAdaptor_TopolTool) aTT2 = new BRepTopAdaptor_TopolTool();
|
||||
|
||||
try {
|
||||
IntPatch_ImpImpIntersection anIIInt (aGA1, aTT1, aGA2, aTT2, aPrec, aPrec);
|
||||
IntPatch_ImpImpIntersection anIIInt(aGA1, aTT1, aGA2, aTT2, theLinTol, theLinTol);
|
||||
if (!anIIInt.IsDone() || anIIInt.IsEmpty())
|
||||
return Standard_False;
|
||||
|
||||
@@ -357,22 +372,6 @@ static Standard_Boolean IsSameDomain(const TopoDS_Face& aFace,
|
||||
}
|
||||
}
|
||||
|
||||
// case of two planar surfaces:
|
||||
// all kinds of surfaces checked, including b-spline and bezier
|
||||
GeomLib_IsPlanarSurface aPlanarityChecker1 (S1, aPrec);
|
||||
if (aPlanarityChecker1.IsPlanar()) {
|
||||
GeomLib_IsPlanarSurface aPlanarityChecker2 (S2, aPrec);
|
||||
if (aPlanarityChecker2.IsPlanar()) {
|
||||
gp_Pln aPln1 = aPlanarityChecker1.Plan();
|
||||
gp_Pln aPln2 = aPlanarityChecker2.Plan();
|
||||
|
||||
if (aPln1.Position().Direction().IsParallel(aPln2.Position().Direction(),Precision::Angular()) &&
|
||||
aPln1.Distance(aPln2) < aPrec) {
|
||||
return Standard_True;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// case of two cylindrical surfaces, at least one of which is a swept surface
|
||||
// swept surfaces: SurfaceOfLinearExtrusion, SurfaceOfRevolution
|
||||
if ((S1->IsKind(STANDARD_TYPE(Geom_CylindricalSurface)) ||
|
||||
@@ -382,14 +381,14 @@ static Standard_Boolean IsSameDomain(const TopoDS_Face& aFace,
|
||||
{
|
||||
gp_Cylinder aCyl1, aCyl2;
|
||||
if (getCylinder(S1, aCyl1) && getCylinder(S2, aCyl2)) {
|
||||
if (fabs(aCyl1.Radius() - aCyl2.Radius()) < aPrec) {
|
||||
if (fabs(aCyl1.Radius() - aCyl2.Radius()) < theLinTol) {
|
||||
gp_Dir aDir1 = aCyl1.Position().Direction();
|
||||
gp_Dir aDir2 = aCyl2.Position().Direction();
|
||||
if (aDir1.IsParallel(aDir2, Precision::Angular())) {
|
||||
gp_Pnt aLoc1 = aCyl1.Location();
|
||||
gp_Pnt aLoc2 = aCyl2.Location();
|
||||
gp_Vec aVec12 (aLoc1, aLoc2);
|
||||
if (aVec12.SquareMagnitude() < aPrec*aPrec ||
|
||||
if (aVec12.SquareMagnitude() < theLinTol*theLinTol ||
|
||||
aVec12.IsParallel(aDir1, Precision::Angular())) {
|
||||
return Standard_True;
|
||||
}
|
||||
@@ -1055,8 +1054,11 @@ static Standard_Boolean MergeSeq (TopTools_SequenceOfShape& SeqEdges,
|
||||
k++;
|
||||
for (Standard_Integer j = 2; j <= SeqOfSubsSeqOfEdges(i).SeqsEdges.Length(); j++)
|
||||
{
|
||||
TopoDS_Shape OldEdge = NewEdges2OldEdges(SeqOfSubsSeqOfEdges(i).SeqsEdges(j));
|
||||
theOldShapes.Bind(OldEdge, SeqOfSubsSeqOfEdges(i).UnionEdges);
|
||||
const TopoDS_Shape& anOldEdge = SeqOfSubsSeqOfEdges(i).SeqsEdges(j);
|
||||
const TopoDS_Shape* pOrigEdge = NewEdges2OldEdges.Seek(anOldEdge);
|
||||
if (!pOrigEdge)
|
||||
pOrigEdge = &anOldEdge;
|
||||
theOldShapes.Bind(*pOrigEdge, SeqOfSubsSeqOfEdges(i).UnionEdges);
|
||||
theContext->Remove(SeqOfSubsSeqOfEdges(i).SeqsEdges(j));
|
||||
}
|
||||
}
|
||||
@@ -1107,7 +1109,9 @@ static void CheckSharedVertices(const TopTools_SequenceOfShape& theSeqEdges,
|
||||
//=======================================================================
|
||||
|
||||
ShapeUpgrade_UnifySameDomain::ShapeUpgrade_UnifySameDomain()
|
||||
: myUnifyFaces (Standard_True),
|
||||
: myLinTol(Precision::Confusion()),
|
||||
myAngTol(Precision::Angular()),
|
||||
myUnifyFaces(Standard_True),
|
||||
myUnifyEdges (Standard_True),
|
||||
myConcatBSplines (Standard_False),
|
||||
myAllowInternal (Standard_False)
|
||||
@@ -1125,7 +1129,9 @@ ShapeUpgrade_UnifySameDomain::ShapeUpgrade_UnifySameDomain(const TopoDS_Shape& a
|
||||
const Standard_Boolean UnifyFaces,
|
||||
const Standard_Boolean ConcatBSplines)
|
||||
: myInitShape (aShape),
|
||||
myUnifyFaces (UnifyFaces),
|
||||
myLinTol(Precision::Confusion()),
|
||||
myAngTol(Precision::Angular()),
|
||||
myUnifyFaces(UnifyFaces),
|
||||
myUnifyEdges (UnifyEdges),
|
||||
myConcatBSplines (ConcatBSplines),
|
||||
myAllowInternal (Standard_False),
|
||||
@@ -1297,7 +1303,7 @@ void ShapeUpgrade_UnifySameDomain::IntUnifyFaces(const TopoDS_Shape& theInpShape
|
||||
if (IsCheckSharedEdgeOri && !CheckSharedEdgeOri(aFace, anCheckedFace, edge) )
|
||||
continue;
|
||||
|
||||
if (IsSameDomain(aFace,anCheckedFace)) {
|
||||
if (IsSameDomain(aFace,anCheckedFace, myLinTol, myAngTol)) {
|
||||
|
||||
// hotfix for 27271: prevent merging along periodic direction.
|
||||
if (IsLikeSeam(edge, aFace, aBaseSurface))
|
||||
|
@@ -62,7 +62,19 @@ public:
|
||||
//! topology. Without this flag merging through multi connected edge
|
||||
//! is forbidden. Default value is false.
|
||||
Standard_EXPORT void AllowInternalEdges (const Standard_Boolean theValue);
|
||||
|
||||
|
||||
//! Sets the linear tolerance. Default value is Precision::Confusion().
|
||||
void SetLinearTolerance(const Standard_Real theValue)
|
||||
{
|
||||
myLinTol = theValue;
|
||||
}
|
||||
|
||||
//! Sets the angular tolerance. Default value is Precision::Angular().
|
||||
void SetAngularTolerance(const Standard_Real theValue)
|
||||
{
|
||||
myAngTol = theValue;
|
||||
}
|
||||
|
||||
//! Builds the resulting shape
|
||||
Standard_EXPORT void Build();
|
||||
|
||||
@@ -100,6 +112,8 @@ private:
|
||||
Standard_Boolean IsCheckSharedEdgeOri);
|
||||
|
||||
TopoDS_Shape myInitShape;
|
||||
Standard_Real myLinTol;
|
||||
Standard_Real myAngTol;
|
||||
Standard_Boolean myUnifyFaces;
|
||||
Standard_Boolean myUnifyEdges;
|
||||
Standard_Boolean myConcatBSplines;
|
||||
|
@@ -611,7 +611,10 @@ void StdPrs_Isolines::UVIsoParameters (const TopoDS_Face& theFace,
|
||||
aVmax = Min (aVmax, theUVLimit);
|
||||
|
||||
TopLoc_Location aLocation;
|
||||
Handle(Geom_Surface) aSurface = BRep_Tool::Surface (theFace, aLocation);
|
||||
const Handle(Geom_Surface)& aSurface = BRep_Tool::Surface (theFace, aLocation);
|
||||
|
||||
if (aSurface.IsNull())
|
||||
return;
|
||||
|
||||
const Standard_Boolean isUClosed = aSurface->IsUClosed();
|
||||
const Standard_Boolean isVClosed = aSurface->IsVClosed();
|
||||
|
@@ -304,6 +304,9 @@ void StdPrs_WFShape::addEdgesOnTriangulation (const Handle(Prs3d_Presentation)&
|
||||
}
|
||||
}
|
||||
|
||||
if (aNbFree == 0)
|
||||
continue;
|
||||
|
||||
// Allocate the arrays.
|
||||
TColStd_Array1OfInteger aFree (1, 2 * aNbFree);
|
||||
Standard_Integer aNbInternal = (3 * aNbTriangles - aNbFree) / 2;
|
||||
|
@@ -11,3 +11,4 @@ TKHLR
|
||||
TKService
|
||||
TKGeomAlgo
|
||||
TKV3d
|
||||
TKSTL
|
@@ -650,7 +650,15 @@ VrmlData_ErrorStatus VrmlData_ArrayVec3d::ReadArray
|
||||
// Read the body of the data node (list of triplets)
|
||||
if (OK(aStatus) && OK(aStatus, VrmlData_Scene::ReadLine(theBuffer))) {
|
||||
if (theBuffer.LinePtr[0] != '[') // opening bracket
|
||||
aStatus = VrmlData_VrmlFormatError;
|
||||
{
|
||||
// Handle case when brackets are ommited for single element of array
|
||||
gp_XYZ anXYZ;
|
||||
// Read three numbers (XYZ value)
|
||||
if (!OK(aStatus, Scene().ReadXYZ(theBuffer, anXYZ,
|
||||
isScale, Standard_False)))
|
||||
aStatus = VrmlData_VrmlFormatError;
|
||||
vecValues.Append(anXYZ);
|
||||
}
|
||||
else {
|
||||
theBuffer.LinePtr++;
|
||||
for(;;) {
|
||||
|
@@ -203,6 +203,10 @@ VrmlData_ErrorStatus VrmlData_Group::Read (VrmlData_InBuffer& theBuffer)
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "collide")) {
|
||||
TCollection_AsciiString aDummy;
|
||||
aStatus = Scene().ReadWord (theBuffer, aDummy);
|
||||
}
|
||||
else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "Separator") ||
|
||||
VRMLDATA_LCOMPARE (theBuffer.LinePtr, "Switch")) {
|
||||
Standard_Boolean isBracketed (Standard_False);
|
||||
|
@@ -29,6 +29,26 @@
|
||||
#include <Poly.hxx>
|
||||
#include <TShort_HArray1OfShortReal.hxx>
|
||||
|
||||
#include <TopoDS_Face.hxx>
|
||||
#include <BRep_Tool.hxx>
|
||||
#include <TopoDS_Vertex.hxx>
|
||||
#include <TopoDS_Wire.hxx>
|
||||
#include <BRepBuilderAPI_Sewing.hxx>
|
||||
#include <TopoDS_Compound.hxx>
|
||||
#include <BRep_Builder.hxx>
|
||||
#include <TopExp_Explorer.hxx>
|
||||
#include <TopoDS.hxx>
|
||||
#include <BRepBuilderAPI_CellFilter.hxx>
|
||||
#include <StlMesh_Mesh.hxx>
|
||||
#include <StlMesh_MeshExplorer.hxx>
|
||||
#include <BRepBuilderAPI_MakeVertex.hxx>
|
||||
#include <BRepBuilderAPI_MakePolygon.hxx>
|
||||
#include <BRepBuilderAPI_MakeFace.hxx>
|
||||
#include <StlAPI.hxx>
|
||||
#include <ShapeUpgrade_UnifySameDomain.hxx>
|
||||
#include <BRepClass3d_SolidClassifier.hxx>
|
||||
#include <ShapeUpgrade_CombineToCylinder.hxx>
|
||||
|
||||
IMPLEMENT_STANDARD_RTTIEXT(VrmlData_IndexedFaceSet,VrmlData_Faceted)
|
||||
|
||||
#ifdef _MSC_VER
|
||||
@@ -36,8 +56,239 @@ IMPLEMENT_STANDARD_RTTIEXT(VrmlData_IndexedFaceSet,VrmlData_Faceted)
|
||||
#pragma warning (disable:4996)
|
||||
#endif
|
||||
|
||||
// Auxiliary tools
|
||||
namespace
|
||||
{
|
||||
// Tool to get triangles from triangulation taking into account face
|
||||
// orientation and location
|
||||
class TriangleAccessor
|
||||
{
|
||||
public:
|
||||
TriangleAccessor (const TopoDS_Face& aFace)
|
||||
{
|
||||
TopLoc_Location aLoc;
|
||||
myPoly = BRep_Tool::Triangulation (aFace, aLoc);
|
||||
myTrsf = aLoc.Transformation();
|
||||
myNbTriangles = (myPoly.IsNull() ? 0 : myPoly->Triangles().Length());
|
||||
myInvert = (aFace.Orientation() == TopAbs_REVERSED);
|
||||
if (myTrsf.IsNegative())
|
||||
myInvert = ! myInvert;
|
||||
}
|
||||
|
||||
int NbTriangles () const { return myNbTriangles; }
|
||||
|
||||
// get i-th triangle and outward normal
|
||||
void GetTriangle (int iTri, gp_Vec &theNormal, gp_Pnt &thePnt1, gp_Pnt &thePnt2, gp_Pnt &thePnt3)
|
||||
{
|
||||
// get positions of nodes
|
||||
int iNode1, iNode2, iNode3;
|
||||
myPoly->Triangles()(iTri).Get (iNode1, iNode2, iNode3);
|
||||
thePnt1 = myPoly->Nodes()(iNode1);
|
||||
thePnt2 = myPoly->Nodes()(myInvert ? iNode3 : iNode2);
|
||||
thePnt3 = myPoly->Nodes()(myInvert ? iNode2 : iNode3);
|
||||
|
||||
// apply transormation if not identity
|
||||
if (myTrsf.Form() != gp_Identity)
|
||||
{
|
||||
thePnt1.Transform (myTrsf);
|
||||
thePnt2.Transform (myTrsf);
|
||||
thePnt3.Transform (myTrsf);
|
||||
}
|
||||
|
||||
// calculate normal
|
||||
theNormal = (thePnt2.XYZ() - thePnt1.XYZ()) ^ (thePnt3.XYZ() - thePnt1.XYZ());
|
||||
Standard_Real aNorm = theNormal.Magnitude();
|
||||
if (aNorm > gp::Resolution())
|
||||
theNormal /= aNorm;
|
||||
}
|
||||
|
||||
private:
|
||||
Handle(Poly_Triangulation) myPoly;
|
||||
gp_Trsf myTrsf;
|
||||
int myNbTriangles;
|
||||
bool myInvert;
|
||||
};
|
||||
|
||||
// convert to float and, on big-endian platform, to little-endian representation
|
||||
inline float convertFloat (Standard_Real aValue)
|
||||
{
|
||||
#ifdef OCCT_BINARY_FILE_DO_INVERSE
|
||||
return OSD_BinaryFile::InverseShortReal ((float)aValue);
|
||||
#else
|
||||
return (float)aValue;
|
||||
#endif
|
||||
}
|
||||
|
||||
// A static method adding nodes to a mesh and keeping coincident (sharing) nodes.
|
||||
static Standard_Integer AddVertex(Handle(StlMesh_Mesh)& mesh,
|
||||
BRepBuilderAPI_CellFilter& filter,
|
||||
BRepBuilderAPI_VertexInspector& inspector,
|
||||
const gp_XYZ& p)
|
||||
{
|
||||
Standard_Integer index;
|
||||
inspector.SetCurrent(p);
|
||||
gp_XYZ minp = inspector.Shift(p, -Precision::Confusion());
|
||||
gp_XYZ maxp = inspector.Shift(p, +Precision::Confusion());
|
||||
filter.Inspect(minp, maxp, inspector);
|
||||
const TColStd_ListOfInteger& indices = inspector.ResInd();
|
||||
if (indices.IsEmpty() == Standard_False)
|
||||
{
|
||||
index = indices.First(); // it should be only one
|
||||
inspector.ClearResList();
|
||||
}
|
||||
else
|
||||
{
|
||||
index = mesh->AddVertex(p.X(), p.Y(), p.Z());
|
||||
filter.Add(index, p);
|
||||
inspector.Add(p);
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
void createFromMesh(Handle(TopoDS_TShape)& theShapeWithMesh)
|
||||
{
|
||||
TopoDS_Shape aShape;
|
||||
//aShape.Orientation(TopAbs_FORWARD);
|
||||
|
||||
aShape.TShape(theShapeWithMesh);
|
||||
if (aShape.IsNull())
|
||||
return;
|
||||
|
||||
// Write to STL and then read again to get BRep model (vrml fills only triangulation)
|
||||
//StlAPI::Write(aShape, "D:/Temp/tempfile");
|
||||
//StlAPI::Read(aShape, "D:/Temp/tempfile");
|
||||
|
||||
gp_XYZ p1, p2, p3;
|
||||
TopoDS_Vertex Vertex1, Vertex2, Vertex3;
|
||||
TopoDS_Face AktFace;
|
||||
TopoDS_Wire AktWire;
|
||||
BRepBuilderAPI_Sewing aSewingTool;
|
||||
Standard_Real x1, y1, z1;
|
||||
Standard_Real x2, y2, z2;
|
||||
Standard_Real x3, y3, z3;
|
||||
Standard_Integer i1,i2,i3;
|
||||
|
||||
aSewingTool.Init(1.0e-06,Standard_True);
|
||||
|
||||
TopoDS_Compound aComp;
|
||||
BRep_Builder BuildTool;
|
||||
BuildTool.MakeCompound( aComp );
|
||||
|
||||
Handle(StlMesh_Mesh) aSTLMesh = new StlMesh_Mesh();
|
||||
aSTLMesh->AddDomain();
|
||||
|
||||
// Filter unique vertices to share the nodes of the mesh.
|
||||
BRepBuilderAPI_CellFilter uniqueVertices(Precision::Confusion());
|
||||
BRepBuilderAPI_VertexInspector inspector(Precision::Confusion());
|
||||
|
||||
// Read mesh
|
||||
for (TopExp_Explorer exp (aShape, TopAbs_FACE); exp.More(); exp.Next())
|
||||
{
|
||||
TriangleAccessor aTool (TopoDS::Face (exp.Current()));
|
||||
for (int iTri = 1; iTri <= aTool.NbTriangles(); iTri++)
|
||||
{
|
||||
gp_Vec aNorm;
|
||||
gp_Pnt aPnt1, aPnt2, aPnt3;
|
||||
aTool.GetTriangle(iTri, aNorm, aPnt1, aPnt2, aPnt3);
|
||||
|
||||
i1 = AddVertex(aSTLMesh, uniqueVertices, inspector, aPnt1.XYZ());
|
||||
i2 = AddVertex(aSTLMesh, uniqueVertices, inspector, aPnt2.XYZ());
|
||||
i3 = AddVertex(aSTLMesh, uniqueVertices, inspector, aPnt3.XYZ());
|
||||
aSTLMesh->AddTriangle(i1, i2, i3, aNorm.X(), aNorm.Y(), aNorm.Z());
|
||||
}
|
||||
}
|
||||
|
||||
StlMesh_MeshExplorer aMExp (aSTLMesh);
|
||||
Standard_Integer NumberDomains = aSTLMesh->NbDomains();
|
||||
Standard_Integer iND;
|
||||
for (iND=1;iND<=NumberDomains;iND++)
|
||||
{
|
||||
for (aMExp.InitTriangle (iND); aMExp.MoreTriangle (); aMExp.NextTriangle ())
|
||||
{
|
||||
aMExp.TriangleVertices (x1,y1,z1,x2,y2,z2,x3,y3,z3);
|
||||
p1.SetCoord(x1,y1,z1);
|
||||
p2.SetCoord(x2,y2,z2);
|
||||
p3.SetCoord(x3,y3,z3);
|
||||
|
||||
if ((!(p1.IsEqual(p2,0.0))) && (!(p1.IsEqual(p3,0.0))))
|
||||
{
|
||||
Vertex1 = BRepBuilderAPI_MakeVertex(p1);
|
||||
Vertex2 = BRepBuilderAPI_MakeVertex(p2);
|
||||
Vertex3 = BRepBuilderAPI_MakeVertex(p3);
|
||||
|
||||
AktWire = BRepBuilderAPI_MakePolygon( Vertex1, Vertex2, Vertex3, Standard_True);
|
||||
|
||||
if( !AktWire.IsNull())
|
||||
{
|
||||
AktFace = BRepBuilderAPI_MakeFace( AktWire);
|
||||
if(!AktFace.IsNull())
|
||||
BuildTool.Add( aComp, AktFace );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
aSTLMesh->Clear();
|
||||
|
||||
aSewingTool.Init();
|
||||
aSewingTool.Load( aComp );
|
||||
aSewingTool.Perform();
|
||||
aShape = aSewingTool.SewedShape();
|
||||
if ( aShape.IsNull() )
|
||||
aShape = aComp;
|
||||
|
||||
ShapeUpgrade_UnifySameDomain anUSD(aShape);
|
||||
anUSD.SetLinearTolerance(1e-5);
|
||||
anUSD.Build();
|
||||
aShape = anUSD.Shape();
|
||||
|
||||
if (aShape.ShapeType() == TopAbs_SHELL && TopoDS::Shell(aShape).Closed())
|
||||
{
|
||||
TopoDS_Solid aSolid;
|
||||
TopoDS_Shell aShell = TopoDS::Shell (aShape);
|
||||
if (!aShell.Free ()) {
|
||||
aShell.Free(Standard_True);
|
||||
}
|
||||
BRep_Builder aBuilder;
|
||||
aBuilder.MakeSolid (aSolid);
|
||||
aBuilder.Add (aSolid, aShell);
|
||||
|
||||
Standard_Boolean isOk = Standard_True;
|
||||
try {
|
||||
OCC_CATCH_SIGNALS
|
||||
BRepClass3d_SolidClassifier bsc3d (aSolid);
|
||||
Standard_Real t = Precision::Confusion();
|
||||
bsc3d.PerformInfinitePoint(t);
|
||||
|
||||
if (bsc3d.State() == TopAbs_IN) {
|
||||
TopoDS_Solid aSolid2;
|
||||
aBuilder.MakeSolid (aSolid2);
|
||||
aShell.Reverse();
|
||||
aBuilder.Add (aSolid2, aShell);
|
||||
aSolid = aSolid2;
|
||||
}
|
||||
}
|
||||
catch (Standard_Failure) { isOk = Standard_False; }
|
||||
if (isOk) aShape = aSolid;
|
||||
}
|
||||
|
||||
// Trying to apply "Combine to Cylinder"
|
||||
|
||||
//ShapeUpgrade_CombineToCylinder cmb2Cyl;
|
||||
//Standard_Boolean isOk = Standard_True;
|
||||
//try {
|
||||
// OCC_CATCH_SIGNALS
|
||||
// cmb2Cyl.SetShape(aShape);
|
||||
// cmb2Cyl.SetAngularTolerance(20);
|
||||
// cmb2Cyl.SetLinearTolerance(3);
|
||||
// cmb2Cyl.Build();
|
||||
//}
|
||||
//catch (Standard_Failure) { isOk = Standard_False; }
|
||||
//if (isOk && cmb2Cyl.IsDone())
|
||||
// aShape = cmb2Cyl.Shape();
|
||||
|
||||
theShapeWithMesh = aShape.TShape();
|
||||
}
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : readData
|
||||
@@ -210,6 +461,7 @@ const Handle(TopoDS_TShape)& VrmlData_IndexedFaceSet::TShape ()
|
||||
|
||||
myIsModified = Standard_False;
|
||||
}
|
||||
//createFromMesh(myTShape);
|
||||
return myTShape;
|
||||
}
|
||||
|
||||
|
@@ -55,34 +55,34 @@ Quantity_Color VrmlData_IndexedLineSet::GetColor
|
||||
|
||||
const Handle(TopoDS_TShape)& VrmlData_IndexedLineSet::TShape ()
|
||||
{
|
||||
if (myNbPolygons == 0)
|
||||
myTShape.Nullify();
|
||||
else if (myIsModified) {
|
||||
Standard_Integer i;
|
||||
BRep_Builder aBuilder;
|
||||
const gp_XYZ * arrNodes = myCoords->Values();
|
||||
//if (myNbPolygons == 0)
|
||||
// myTShape.Nullify();
|
||||
//else if (myIsModified) {
|
||||
// Standard_Integer i;
|
||||
// BRep_Builder aBuilder;
|
||||
// const gp_XYZ * arrNodes = myCoords->Values();
|
||||
|
||||
// Create the Wire
|
||||
TopoDS_Wire aWire;
|
||||
aBuilder.MakeWire(aWire);
|
||||
for (i = 0; i < (int)myNbPolygons; i++) {
|
||||
const Standard_Integer * arrIndice;
|
||||
const Standard_Integer nNodes = Polygon(i, arrIndice);
|
||||
TColgp_Array1OfPnt arrPoint (1, nNodes);
|
||||
TColStd_Array1OfReal arrParam (1, nNodes);
|
||||
for (Standard_Integer j = 0; j < nNodes; j++) {
|
||||
arrPoint(j+1).SetXYZ (arrNodes[arrIndice[j]]);
|
||||
arrParam(j+1) = j;
|
||||
}
|
||||
const Handle(Poly_Polygon3D) aPolyPolygon =
|
||||
new Poly_Polygon3D (arrPoint, arrParam);
|
||||
TopoDS_Edge anEdge;
|
||||
aBuilder.MakeEdge (anEdge, aPolyPolygon);
|
||||
aBuilder.Add (aWire, anEdge);
|
||||
}
|
||||
myTShape = aWire.TShape();
|
||||
}
|
||||
return myTShape;
|
||||
// // Create the Wire
|
||||
// TopoDS_Wire aWire;
|
||||
// aBuilder.MakeWire(aWire);
|
||||
// for (i = 0; i < (int)myNbPolygons; i++) {
|
||||
// const Standard_Integer * arrIndice;
|
||||
// const Standard_Integer nNodes = Polygon(i, arrIndice);
|
||||
// TColgp_Array1OfPnt arrPoint (1, nNodes);
|
||||
// TColStd_Array1OfReal arrParam (1, nNodes);
|
||||
// for (Standard_Integer j = 0; j < nNodes; j++) {
|
||||
// arrPoint(j+1).SetXYZ (arrNodes[arrIndice[j]]);
|
||||
// arrParam(j+1) = j;
|
||||
// }
|
||||
// const Handle(Poly_Polygon3D) aPolyPolygon =
|
||||
// new Poly_Polygon3D (arrPoint, arrParam);
|
||||
// TopoDS_Edge anEdge;
|
||||
// aBuilder.MakeEdge (anEdge, aPolyPolygon);
|
||||
// aBuilder.Add (aWire, anEdge);
|
||||
// }
|
||||
// myTShape = aWire.TShape();
|
||||
//}
|
||||
return Handle(TopoDS_TShape)();
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
|
@@ -497,6 +497,9 @@ VrmlData_ErrorStatus VrmlData_Scene::createNode
|
||||
else if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "Separator"))
|
||||
aNode = new VrmlData_Group (* this, strName,
|
||||
Standard_False);
|
||||
else if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "Collision"))
|
||||
aNode = new VrmlData_Group (* this, strName,
|
||||
Standard_False);
|
||||
else if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "Switch"))
|
||||
aNode = new VrmlData_Group (* this, strName,
|
||||
Standard_False);
|
||||
|
@@ -52,6 +52,23 @@
|
||||
#include <TDF_Tool.hxx>
|
||||
#include <TopoDS_Shape.hxx>
|
||||
|
||||
#include <BRep_Builder.hxx>
|
||||
#include <OSD_Path.hxx>
|
||||
#include <OSD_DirectoryIterator.hxx>
|
||||
#include <OSD_FileIterator.hxx>
|
||||
#include <TopoDS_Compound.hxx>
|
||||
#include <VrmlData_Scene.hxx>
|
||||
#include <ShapeUpgrade_UnifySameDomain.hxx>
|
||||
#include <TopExp_Explorer.hxx>
|
||||
#include <TopoDS.hxx>
|
||||
#include <XCAFDoc_ColorTool.hxx>
|
||||
#include <BRepClass3d_SolidClassifier.hxx>
|
||||
#include <Poly_Triangulation.hxx>
|
||||
#include <BRepMesh_IncrementalMesh.hxx>
|
||||
#include <Geom_CylindricalSurface.hxx>
|
||||
|
||||
#include <StlAPI.hxx>
|
||||
|
||||
#include <stdio.h>
|
||||
//============================================================
|
||||
// Support for several models in DRAW
|
||||
@@ -517,6 +534,339 @@ static Standard_Integer Expand (Draw_Interpretor& di, Standard_Integer argc, con
|
||||
return 0;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : ReadVrml
|
||||
//purpose : Read VRML file to DECAF document
|
||||
//=======================================================================
|
||||
|
||||
TDF_Label ReadVrmlRec(const OSD_Path& thePath, const Handle(TDocStd_Document)& theDoc, const TDF_Label& theLabel)
|
||||
{
|
||||
TDF_Label aNewLabel;
|
||||
Handle(XCAFDoc_ShapeTool) aShapeTool = XCAFDoc_DocumentTool::ShapeTool( theDoc->Main() );
|
||||
Handle(XCAFDoc_ColorTool) aColorTool = XCAFDoc_DocumentTool::ColorTool( theDoc->Main() );
|
||||
|
||||
// Get path of the VRML file.
|
||||
TCollection_AsciiString aVrmlDir(".");
|
||||
TCollection_AsciiString aDisk = thePath.Disk();
|
||||
TCollection_AsciiString aTrek = thePath.Trek();
|
||||
TCollection_AsciiString aName = thePath.Name();
|
||||
TCollection_AsciiString anExt = thePath.Extension();
|
||||
|
||||
cout << "==============================================================" << endl;
|
||||
|
||||
if (!aTrek.IsEmpty())
|
||||
{
|
||||
if (!aDisk.IsEmpty())
|
||||
aVrmlDir = aDisk;
|
||||
else
|
||||
aVrmlDir.Clear();
|
||||
aTrek.ChangeAll('|', '/');
|
||||
aTrek.ChangeAll('\\', '/');
|
||||
aVrmlDir += aTrek;
|
||||
|
||||
if (!aName.IsEmpty())
|
||||
aVrmlDir += aName;
|
||||
|
||||
if (!anExt.IsEmpty())
|
||||
aVrmlDir += anExt;
|
||||
}
|
||||
|
||||
// Analize the passed Path
|
||||
if (thePath.Extension() == ".wrl")
|
||||
{
|
||||
// Read shape from vrml and add to parent as component
|
||||
TopoDS_Shape aShape ;
|
||||
VrmlData_DataMapOfShapeAppearance aShapeAppMap;
|
||||
filebuf aFic;
|
||||
istream aStream (&aFic);
|
||||
if (aFic.open(aVrmlDir.ToCString(), ios::in))
|
||||
{
|
||||
cout << "Reading file " << aVrmlDir.ToCString() << "..." << endl;
|
||||
|
||||
VrmlData_Scene aScene;
|
||||
aScene.SetVrmlDir(aVrmlDir);
|
||||
aScene << aStream;
|
||||
aFic.close();
|
||||
if (aScene.Status() == VrmlData_StatusOK)
|
||||
{
|
||||
aShape = aScene.GetShape(aShapeAppMap);
|
||||
|
||||
if (aShape.IsNull())
|
||||
{
|
||||
cout << "Shape was not extracted from file " << aVrmlDir.ToCString() << "..." << endl;
|
||||
return aNewLabel;
|
||||
}
|
||||
|
||||
TopExp_Explorer anExp;
|
||||
Quantity_Color aFaceColor;
|
||||
Quantity_Color anEdgeColor(Quantity_NOC_BLACK);
|
||||
for (anExp.Init(aShape, TopAbs_FACE); anExp.More(); anExp.Next())
|
||||
{
|
||||
if (aShapeAppMap.IsBound(anExp.Current().TShape()))
|
||||
{
|
||||
Handle(VrmlData_Appearance) anAppearance = aShapeAppMap.Find(anExp.Current().TShape());
|
||||
if (!anAppearance.IsNull() && !anAppearance->Material().IsNull())
|
||||
{
|
||||
aFaceColor = anAppearance->Material()->DiffuseColor();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Standard_Boolean isSingleShell = Standard_False;
|
||||
//TopoDS_Shell aShell;
|
||||
//for (anExp.Init(aShape, TopAbs_SHELL); anExp.More(); anExp.Next())
|
||||
//{
|
||||
// if (!anExp.Current().IsNull() && anExp.Current().ShapeType() == TopAbs_SHELL)
|
||||
// {
|
||||
// if (!isSingleShell)
|
||||
// {
|
||||
// aShell = TopoDS::Shell(anExp.Current());
|
||||
// isSingleShell = Standard_True;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// isSingleShell = Standard_False;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
//Standard_Boolean hasCylindrical = Standard_False;
|
||||
//if (!aShell.IsNull() && isSingleShell)
|
||||
//{
|
||||
// for (anExp.Init(aShell, TopAbs_FACE); anExp.More(); anExp.Next())
|
||||
// {
|
||||
// if (!anExp.Current().IsNull())
|
||||
// {
|
||||
// const TopoDS_Face& aFace = TopoDS::Face(anExp.Current());
|
||||
// Handle(Geom_CylindricalSurface) aSurf = Handle(Geom_CylindricalSurface)::DownCast(BRep_Tool::Surface(aFace));
|
||||
// if (!aSurf.IsNull())
|
||||
// hasCylindrical = Standard_True;
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
//if (hasCylindrical)
|
||||
// aShape = aShell;
|
||||
//else
|
||||
// isSingleShell = Standard_False;
|
||||
|
||||
//if (!isSingleShell)
|
||||
//{
|
||||
// Standard_Boolean doTriangulation = Standard_False;
|
||||
// for (anExp.Init(aShape, TopAbs_FACE); anExp.More(); anExp.Next())
|
||||
// {
|
||||
// TopLoc_Location aDummy;
|
||||
// if (BRep_Tool::Triangulation(TopoDS::Face(anExp.Current()), aDummy).IsNull())
|
||||
// {
|
||||
// doTriangulation = Standard_True;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
|
||||
// if (doTriangulation)
|
||||
// {
|
||||
// BRepMesh_IncrementalMesh aMesh(aShape, 1);
|
||||
// aMesh.Perform();
|
||||
// if (aMesh.IsDone())
|
||||
// aShape = aMesh.Shape();
|
||||
// }
|
||||
|
||||
// // Write to STL and then read again to get BRep model (vrml fills only triangulation)
|
||||
// StlAPI::Write(aShape, vrmlTempFile);
|
||||
// StlAPI::Read(aShape, vrmlTempFile);
|
||||
//}
|
||||
|
||||
/*if (aShape.IsNull())
|
||||
return aNewLabel;*/
|
||||
|
||||
/*ShapeUpgrade_UnifySameDomain anUSD(aShape);
|
||||
anUSD.SetLinearTolerance(1e-5);
|
||||
anUSD.Build();
|
||||
aShape = anUSD.Shape();
|
||||
|
||||
if (aShape.ShapeType() == TopAbs_SHELL && TopoDS::Shell(aShape).Closed())
|
||||
{
|
||||
TopoDS_Solid aSolid;
|
||||
TopoDS_Shell aShell = TopoDS::Shell (aShape);
|
||||
if (!aShell.Free ()) {
|
||||
aShell.Free(Standard_True);
|
||||
}
|
||||
BRep_Builder aBuilder;
|
||||
aBuilder.MakeSolid (aSolid);
|
||||
aBuilder.Add (aSolid, aShell);
|
||||
|
||||
Standard_Boolean isOk = Standard_True;
|
||||
try {
|
||||
OCC_CATCH_SIGNALS
|
||||
BRepClass3d_SolidClassifier bsc3d (aSolid);
|
||||
Standard_Real t = Precision::Confusion();
|
||||
bsc3d.PerformInfinitePoint(t);
|
||||
|
||||
if (bsc3d.State() == TopAbs_IN) {
|
||||
TopoDS_Solid aSolid2;
|
||||
aBuilder.MakeSolid (aSolid2);
|
||||
aShell.Reverse();
|
||||
aBuilder.Add (aSolid2, aShell);
|
||||
aSolid = aSolid2;
|
||||
}
|
||||
}
|
||||
catch (Standard_Failure) { isOk = Standard_False; }
|
||||
if (isOk) aShape = aSolid;
|
||||
}*/
|
||||
|
||||
if (theLabel.IsNull() || !aShapeTool->IsAssembly(theLabel))
|
||||
{
|
||||
// Add new shape
|
||||
aNewLabel = aShapeTool->AddShape(aShape, Standard_False);
|
||||
cout << "Created new shape " << thePath.Name() << " (free)" << endl;
|
||||
}
|
||||
else if (!theLabel.IsNull() && aShapeTool->IsAssembly(theLabel))
|
||||
{
|
||||
// Add shape as component
|
||||
aNewLabel = aShapeTool->AddComponent(theLabel, aShape);
|
||||
Handle(TDataStd_Name) anAttrName;
|
||||
theLabel.FindAttribute(TDataStd_Name::GetID(), anAttrName);
|
||||
cout << "Created new shape " << thePath.Name() << " as part of " << (anAttrName.IsNull()? "(noname)" : TCollection_AsciiString(anAttrName->Get())) << endl;
|
||||
|
||||
if ( aShapeTool->IsReference(aNewLabel) )
|
||||
{
|
||||
TDF_Label RefLabel;
|
||||
if ( aShapeTool->GetReferredShape(aNewLabel, RefLabel) )
|
||||
aNewLabel = RefLabel;
|
||||
}
|
||||
}
|
||||
|
||||
if (!aNewLabel.IsNull())
|
||||
TDataStd_Name::Set(aNewLabel, thePath.Name());
|
||||
|
||||
aColorTool->SetColor(aNewLabel, aFaceColor, XCAFDoc_ColorSurf);
|
||||
aColorTool->SetColor(aNewLabel, anEdgeColor, XCAFDoc_ColorCurv);
|
||||
return aNewLabel;
|
||||
}
|
||||
else
|
||||
{
|
||||
cout << "Error during reading of vrml file " << aVrmlDir.ToCString() << endl;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cout << "Cannot open file " << aVrmlDir.ToCString() << endl;
|
||||
}
|
||||
}
|
||||
else if (thePath.Extension().IsEmpty())
|
||||
{
|
||||
cout << "Scaning root " << aVrmlDir.ToCString() << "..." << endl;
|
||||
|
||||
OSD_DirectoryIterator aDirIt(thePath, "*");
|
||||
OSD_FileIterator aFileIt(thePath, "*.wrl");
|
||||
|
||||
// Check real dircetories
|
||||
OSD_Path aSubDirPath;
|
||||
TCollection_AsciiString aTempName;
|
||||
Standard_Boolean isSubDirExist = Standard_False;
|
||||
for (; aDirIt.More(); aDirIt.Next())
|
||||
{
|
||||
aDirIt.Values().Path(aSubDirPath);
|
||||
aTempName = aSubDirPath.Name() + aSubDirPath.Extension();
|
||||
if (aTempName != "." && aTempName != "..")
|
||||
{
|
||||
isSubDirExist = Standard_True;
|
||||
break;
|
||||
}
|
||||
}
|
||||
aDirIt.Initialize(thePath, "*"); // Re-initialize
|
||||
|
||||
if (!isSubDirExist && !aFileIt.More())
|
||||
{
|
||||
cout << "No files or directories detected in " << aVrmlDir.ToCString() << endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Create assembly
|
||||
TopoDS_Compound aComp;
|
||||
BRep_Builder aBuilder;
|
||||
aBuilder.MakeCompound(aComp);
|
||||
|
||||
if (theLabel.IsNull() || !aShapeTool->IsAssembly(theLabel))
|
||||
{
|
||||
// Add new shape
|
||||
aNewLabel = aShapeTool->AddShape(aComp);
|
||||
cout << "Created new assembly " << thePath.Name() << " (free)" << endl;
|
||||
}
|
||||
else if (!theLabel.IsNull() && aShapeTool->IsAssembly(theLabel))
|
||||
{
|
||||
// Add shape as component
|
||||
aNewLabel = aShapeTool->AddComponent(theLabel, aComp, Standard_True);
|
||||
Handle(TDataStd_Name) anAttrName;
|
||||
theLabel.FindAttribute(TDataStd_Name::GetID(), anAttrName);
|
||||
cout << "Created new assembly " << thePath.Name() << " as part of " << (anAttrName.IsNull()? "(noname)" : TCollection_AsciiString(anAttrName->Get())) << endl;
|
||||
|
||||
if ( aShapeTool->IsReference(aNewLabel) )
|
||||
{
|
||||
TDF_Label RefLabel;
|
||||
if ( aShapeTool->GetReferredShape(aNewLabel, RefLabel) )
|
||||
aNewLabel = RefLabel;
|
||||
}
|
||||
}
|
||||
|
||||
if (!aNewLabel.IsNull())
|
||||
TDataStd_Name::Set(aNewLabel, thePath.Name());
|
||||
|
||||
// Add components
|
||||
for (; aDirIt.More(); aDirIt.Next())
|
||||
{
|
||||
aDirIt.Values().Path(aSubDirPath);
|
||||
aTempName = aSubDirPath.Name() + aSubDirPath.Extension();
|
||||
if (aTempName == "." || aTempName == "..")
|
||||
continue;
|
||||
aSubDirPath.SetDisk(thePath.Disk());
|
||||
aSubDirPath.SetTrek(thePath.Trek() + thePath.Name());
|
||||
ReadVrmlRec(aSubDirPath, theDoc, aNewLabel);
|
||||
}
|
||||
|
||||
for (; aFileIt.More(); aFileIt.Next())
|
||||
{
|
||||
aFileIt.Values().Path(aSubDirPath);
|
||||
aSubDirPath.SetDisk(thePath.Disk());
|
||||
aSubDirPath.SetTrek(thePath.Trek() + thePath.Name());
|
||||
ReadVrmlRec(aSubDirPath, theDoc, aNewLabel);
|
||||
}
|
||||
|
||||
aShapeTool->UpdateAssembly(aNewLabel);
|
||||
}
|
||||
// At the end of operation update assemblies
|
||||
}
|
||||
else
|
||||
{
|
||||
cout << "Unknown file format: " << thePath.Extension() << endl;
|
||||
}
|
||||
|
||||
return aNewLabel;
|
||||
}
|
||||
|
||||
static Standard_Integer ReadVrml (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
|
||||
{
|
||||
if ( argc != 3 ) {
|
||||
di << "Use: " << argv[0] << " Doc Path: Read VRML assembly to DECAF document\n";
|
||||
return 0;
|
||||
}
|
||||
|
||||
Handle(TDocStd_Document) doc;
|
||||
if (!DDocStd::GetDocument(argv[1],doc,Standard_False))
|
||||
{
|
||||
Handle(TDocStd_Application) A = DDocStd::GetApplication();
|
||||
A->NewDocument("BinXCAF",doc);
|
||||
TDataStd_Name::Set(doc->GetData()->Root(),argv[1]);
|
||||
Handle(DDocStd_DrawDocument) DD = new DDocStd_DrawDocument(doc);
|
||||
Draw::Set(argv[1], DD);
|
||||
}
|
||||
|
||||
ReadVrmlRec(OSD_Path(argv[2]), doc, TDF_Label());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void XDEDRAW_Common::InitCommands(Draw_Interpretor& di) {
|
||||
|
||||
static Standard_Boolean initactor = Standard_False;
|
||||
@@ -537,4 +887,5 @@ void XDEDRAW_Common::InitCommands(Draw_Interpretor& di) {
|
||||
di.Add("XExpand", "XExpand Doc recursively(0/1) or XExpand Doc recursively(0/1) label1 abel2 ..."
|
||||
"or XExpand Doc recursively(0/1) shape1 shape2 ...",__FILE__, Expand, g);
|
||||
|
||||
di.Add("ReadVrml" , "Doc Path: Read VRML assembly to DECAF document" ,__FILE__, ReadVrml, g);
|
||||
}
|
||||
|
@@ -273,14 +273,15 @@ static Standard_Integer nbComponents (Draw_Interpretor& di, Standard_Integer arg
|
||||
|
||||
static Standard_Integer addComponent (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
|
||||
{
|
||||
if (argc!=4) {
|
||||
di<<"Use: "<<argv[0]<<" DocName Label Shape \n";
|
||||
if (argc<4) {
|
||||
di<<"Use: "<<argv[0]<<" DocName Label Shape [int makeAssembly (1/0)]\n";
|
||||
return 1;
|
||||
}
|
||||
Handle(TDocStd_Document) Doc;
|
||||
DDocStd::GetDocument(argv[1], Doc);
|
||||
if ( Doc.IsNull() ) { di << argv[1] << " is not a document\n"; return 1; }
|
||||
|
||||
Standard_Boolean makeAssembly = Standard_True;
|
||||
if ( argc==5 && Draw::Atoi(argv[4]) == 0 ) makeAssembly = Standard_False;
|
||||
TDF_Label aLabel;
|
||||
TDF_Tool::Label(Doc->GetData(), argv[2], aLabel);
|
||||
TopoDS_Shape aShape;
|
||||
@@ -288,7 +289,7 @@ static Standard_Integer addComponent (Draw_Interpretor& di, Standard_Integer arg
|
||||
Handle(XCAFDoc_ShapeTool) myAssembly = XCAFDoc_DocumentTool::ShapeTool(Doc->Main());
|
||||
// XCAFDoc_ShapeTool myAssembly->
|
||||
// myAssembly->Init(Doc);
|
||||
myAssembly->AddComponent(aLabel, aShape);
|
||||
myAssembly->AddComponent(aLabel, aShape, makeAssembly);
|
||||
TCollection_AsciiString Entry;
|
||||
TDF_Tool::Entry(aLabel, Entry);
|
||||
di << Entry.ToCString();
|
||||
|
18
tests/bugs/heal/bug27729
Normal file
18
tests/bugs/heal/bug27729
Normal file
@@ -0,0 +1,18 @@
|
||||
puts "========"
|
||||
puts "OCC27729"
|
||||
puts "========"
|
||||
puts ""
|
||||
#######################################################################
|
||||
# UnifySameDomain: allow the user to specify linear and angular tolerances
|
||||
#######################################################################
|
||||
|
||||
restore [locate_data_file a_1275.brep] a
|
||||
|
||||
unifysamedom r a -t 0.1 -a 0.08
|
||||
|
||||
regexp {FACE *: *(\d*)} [nbshapes r] full nbfaces
|
||||
if {$nbfaces > 1000} {
|
||||
puts "Error: number of faces in the result is too large"
|
||||
}
|
||||
|
||||
checkview -display r -2d -path ${imagedir}/${test_image}.png
|
Reference in New Issue
Block a user