1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-08-14 13:30:48 +03:00

Compare commits

..

1 Commits

Author SHA1 Message Date
kgv
3a0ab2bfb1 0032819: Data Exchange - VrmlAPI_Writer does not write all colors
VrmlData_ShapeConvert::addShape() - fixed handling of colors assigned to Compound instead of a Face.
RWMesh_FaceIterator is now used to dispatch colors and skip Faces without triangulation.
2022-02-09 23:33:47 +03:00
28 changed files with 408 additions and 2188 deletions

View File

@@ -454,7 +454,6 @@ t TKRWMesh
n RWGltf
n RWMesh
n RWObj
n RWPly
n DFBrowser
n DFBrowserPane
n DFBrowserPaneXDE

View File

@@ -1,307 +0,0 @@
// Copyright (c) 2021 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 <BRepLib_PointCloudShape.hxx>
#include <BRep_Tool.hxx>
#include <BRepGProp.hxx>
#include <BRepLib_ToolTriangulatedShape.hxx>
#include <BRepTools.hxx>
#include <BRepTopAdaptor_FClass2d.hxx>
#include <Geom_Surface.hxx>
#include <GProp_GProps.hxx>
#include <gp_Pnt.hxx>
#include <gp_Vec.hxx>
#include <Precision.hxx>
#include <TopExp_Explorer.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Face.hxx>
#include <TopoDS_Shape.hxx>
#include <random>
// =======================================================================
// function : BRepLib_PointCloudShape
// purpose :
// =======================================================================
BRepLib_PointCloudShape::BRepLib_PointCloudShape (const TopoDS_Shape& theShape,
const Standard_Real theTol)
: myShape (theShape),
myDist (0.0),
myTol (theTol),
myNbPoints (0)
{
//
}
// =======================================================================
// function : ~BRepLib_PointCloudShape
// purpose :
// =======================================================================
BRepLib_PointCloudShape::~BRepLib_PointCloudShape()
{
//
}
// =======================================================================
// function : NbPointsByDensity
// purpose :
// =======================================================================
Standard_Integer BRepLib_PointCloudShape::NbPointsByDensity (const Standard_Real theDensity)
{
clear();
Standard_Real aDensity = (theDensity < Precision::Confusion() ? computeDensity() : theDensity);
if (aDensity < Precision::Confusion())
{
return 0;
}
Standard_Integer aNbPoints = 0;
for (TopExp_Explorer aExpF(myShape, TopAbs_FACE); aExpF.More(); aExpF.Next())
{
Standard_Real anArea = faceArea(aExpF.Current());
Standard_Integer aNbPnts = Max ((Standard_Integer)std::ceil(anArea / theDensity), 1);
myFacePoints.Bind(aExpF.Current(), aNbPnts);
aNbPoints+= aNbPnts;
}
return aNbPoints;
}
// =======================================================================
// function : GeneratePointsByDensity
// purpose :
// =======================================================================
Standard_Boolean BRepLib_PointCloudShape::GeneratePointsByDensity (const Standard_Real theDensity)
{
if (myFacePoints.IsEmpty())
{
if (NbPointsByDensity (theDensity) == 0)
{
return Standard_False;
}
}
Standard_Integer aNbAdded = 0;
for (TopExp_Explorer aExpF (myShape, TopAbs_FACE); aExpF.More(); aExpF.Next())
{
if (addDensityPoints (aExpF.Current()))
{
aNbAdded++;
}
}
return (aNbAdded > 0);
}
// =======================================================================
// function : GeneratePointsByTriangulation
// purpose :
// =======================================================================
Standard_Boolean BRepLib_PointCloudShape::GeneratePointsByTriangulation()
{
clear();
Standard_Integer aNbAdded = 0;
for (TopExp_Explorer aExpF (myShape, TopAbs_FACE); aExpF.More(); aExpF.Next())
{
if (addTriangulationPoints (aExpF.Current()))
{
aNbAdded++;
}
}
return (aNbAdded > 0);
}
// =======================================================================
// function : faceArea
// purpose :
// =======================================================================
Standard_Real BRepLib_PointCloudShape::faceArea (const TopoDS_Shape& theShape)
{
Standard_Real anArea = 0.0;
if (myFaceArea.Find (theShape, anArea))
{
return anArea;
}
GProp_GProps aFaceProps;
BRepGProp::SurfaceProperties (theShape, aFaceProps);
anArea = aFaceProps.Mass();
myFaceArea.Bind (theShape, anArea);
return anArea;
}
// =======================================================================
// function : computeDensity
// purpose :
// =======================================================================
Standard_Real BRepLib_PointCloudShape::computeDensity()
{
// at first step find the face with smallest area
Standard_Real anAreaMin = Precision::Infinite();
for (TopExp_Explorer aExpF (myShape, TopAbs_FACE); aExpF.More(); aExpF.Next())
{
Standard_Real anArea = faceArea (aExpF.Current());
if (anArea < myTol * myTol)
{
continue;
}
if (anArea < anAreaMin)
{
anAreaMin = anArea;
}
}
return anAreaMin * 0.1;
}
// =======================================================================
// function : NbPointsByTriangulation
// purpose :
// =======================================================================
Standard_Integer BRepLib_PointCloudShape::NbPointsByTriangulation() const
{
// at first step find the face with smallest area
Standard_Integer aNbPoints = 0;
for (TopExp_Explorer aExpF (myShape, TopAbs_FACE); aExpF.More(); aExpF.Next())
{
TopLoc_Location aLoc;
Handle(Poly_Triangulation) aTriangulation = BRep_Tool::Triangulation (TopoDS::Face (aExpF.Current()), aLoc);
if (aTriangulation.IsNull())
{
continue;
}
aNbPoints += aTriangulation->NbNodes();
}
return aNbPoints;
}
// =======================================================================
// function : addDensityPoints
// purpose :
// =======================================================================
Standard_Boolean BRepLib_PointCloudShape::addDensityPoints (const TopoDS_Shape& theFace)
{
//addition of the points with specified density on the face by random way
Standard_Integer aNbPnts = (myFacePoints.IsBound (theFace) ? myFacePoints.Find (theFace) : 0);
if (aNbPnts == 0)
{
return Standard_False;
}
TopoDS_Face aFace = TopoDS::Face (theFace);
Standard_Real anUMin = 0.0, anUMax = 0.0, aVMin = 0.0, aVMax = 0.0;
BRepTools::UVBounds (aFace, anUMin, anUMax, aVMin, aVMax);
BRepTopAdaptor_FClass2d aClassifier (aFace, Precision::Confusion());
TopLoc_Location aLoc = theFace.Location();
const gp_Trsf& aTrsf = aLoc.Transformation();
TopLoc_Location aLoc1;
Handle(Geom_Surface) aSurf = BRep_Tool::Surface (aFace, aLoc1);
if (aSurf.IsNull())
{
return Standard_False;
}
std::mt19937 aRandomGenerator(0);
std::uniform_real_distribution<> anUDistrib(anUMin, anUMax);
std::uniform_real_distribution<> aVDistrib (aVMin, aVMax);
for (Standard_Integer nbCurPnts = 1; nbCurPnts <= aNbPnts;)
{
const Standard_Real aU = anUDistrib(aRandomGenerator);
const Standard_Real aV = aVDistrib (aRandomGenerator);
gp_Pnt2d aUVNode (aU, aV);
const TopAbs_State aState = aClassifier.Perform (aUVNode);
if (aState == TopAbs_OUT)
{
continue;
}
nbCurPnts++;
gp_Pnt aP1;
gp_Vec dU, dV;
aSurf->D1 (aU, aV, aP1, dU, dV);
gp_Vec aNorm = dU ^ dV;
if (aFace.Orientation() == TopAbs_REVERSED)
{
aNorm.Reverse();
}
const Standard_Real aNormMod = aNorm.Magnitude();
if (aNormMod > gp::Resolution())
{
aNorm /= aNormMod;
}
if (myDist > Precision::Confusion())
{
std::uniform_real_distribution<> aDistanceDistrib (0.0, myDist);
gp_XYZ aDeflPoint = aP1.XYZ() + aNorm.XYZ() * aDistanceDistrib (aRandomGenerator);
aP1.SetXYZ (aDeflPoint);
}
aP1.Transform (aTrsf);
if (aNormMod > gp::Resolution())
{
aNorm = gp_Dir (aNorm).Transformed (aTrsf);
}
addPoint (aP1, aNorm, aUVNode, aFace);
}
return Standard_True;
}
// =======================================================================
// function : addTriangulationPoints
// purpose :
// =======================================================================
Standard_Boolean BRepLib_PointCloudShape::addTriangulationPoints (const TopoDS_Shape& theFace)
{
TopLoc_Location aLoc;
TopoDS_Face aFace = TopoDS::Face (theFace);
Handle(Poly_Triangulation) aTriangulation = BRep_Tool::Triangulation (aFace, aLoc);
if (aTriangulation.IsNull())
{
return Standard_False;
}
TopLoc_Location aLoc1;
Handle(Geom_Surface) aSurf = BRep_Tool::Surface (aFace, aLoc1);
const gp_Trsf& aTrsf = aLoc.Transformation();
BRepLib_ToolTriangulatedShape::ComputeNormals (aFace, aTriangulation);
Standard_Boolean aHasUVNode = aTriangulation->HasUVNodes();
for (Standard_Integer aNodeIter = 1; aNodeIter <= aTriangulation->NbNodes(); ++aNodeIter)
{
gp_Pnt aP1 = aTriangulation->Node (aNodeIter);
gp_Dir aNormal = aTriangulation->Normal(aNodeIter);
if (!aLoc.IsIdentity())
{
aP1 .Transform (aTrsf);
aNormal.Transform (aTrsf);
}
const gp_Pnt2d anUVNode = aHasUVNode ? aTriangulation->UVNode (aNodeIter) : gp_Pnt2d();
addPoint (aP1, aNormal, anUVNode, aFace);
}
return Standard_True;
}
// =======================================================================
// function : clear
// purpose :
// =======================================================================
void BRepLib_PointCloudShape::clear()
{
myFaceArea.Clear();
myFacePoints.Clear();
}

View File

@@ -1,116 +0,0 @@
// Copyright (c) 2021 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 _BRepLib_PointCloudShape_HeaderFile
#define _BRepLib_PointCloudShape_HeaderFile
#include <TopTools_DataMapOfShapeInteger.hxx>
#include <TopTools_DataMapOfShapeReal.hxx>
#include <Quantity_Color.hxx>
#include <Precision.hxx>
//! This tool is intended to get points from shape with specified distance from shape along normal.
//! Can be used to simulation of points obtained in result of laser scan of shape.
//! There are 2 ways for generation points by shape:
//! 1. Generation points with specified density
//! 2. Generation points using triangulation Nodes
//! Generation of points by density using the GeneratePointsByDensity() function is not thread safe.
class BRepLib_PointCloudShape
{
public:
DEFINE_STANDARD_ALLOC
//! Constructor initialized by shape
Standard_EXPORT BRepLib_PointCloudShape (const TopoDS_Shape& theShape = TopoDS_Shape(),
const Standard_Real theTol = Precision::Confusion());
//! Virtual destructor
Standard_EXPORT virtual ~BRepLib_PointCloudShape();
//! Return loaded shape.
const TopoDS_Shape& Shape() const { return myShape; }
//! Set shape.
void SetShape (const TopoDS_Shape& theShape) { myShape = theShape; }
//! Return tolerance.
Standard_Real Tolerance() const { return myTol; }
//! Set tolerance.
void SetTolerance (Standard_Real theTol) { myTol = theTol; }
//! Returns value of the distance to define deflection of points from shape along normal to shape; 0.0 by default.
Standard_Real GetDistance() const { return myDist; }
//! Sets value of the distance to define deflection of points from shape along normal to shape.
//! Negative values of theDist parameter are ignored.
void SetDistance (const Standard_Real theDist) { myDist = theDist; }
//! Returns size of the point cloud for specified density.
Standard_EXPORT Standard_Integer NbPointsByDensity (const Standard_Real theDensity = 0.0);
//! Returns size of the point cloud for using triangulation.
Standard_EXPORT Standard_Integer NbPointsByTriangulation() const;
//! Computes points with specified density for initial shape.
//! If parameter Density is equal to 0 then density will be computed automatically by criterion:
//! - 10 points per minimal unreduced face area.
//!
//! Note: this function should not be called from concurrent threads without external lock.
Standard_EXPORT Standard_Boolean GeneratePointsByDensity (const Standard_Real theDensity = 0.0);
//! Get points from triangulation existing in the shape.
Standard_EXPORT Standard_Boolean GeneratePointsByTriangulation();
protected:
//! Compute area of the specified face.
Standard_EXPORT Standard_Real faceArea (const TopoDS_Shape& theShape);
//! Computes default density points per face.
Standard_EXPORT Standard_Real computeDensity();
//! Adds points to face in accordance with the specified density randomly in the specified range [0, Dist].
Standard_EXPORT Standard_Boolean addDensityPoints (const TopoDS_Shape& theFace);
//! Adds points to face by nodes of the existing triangulation randomly in the specified range [0, Dist].
Standard_EXPORT Standard_Boolean addTriangulationPoints (const TopoDS_Shape& theFace);
protected:
//! Method to clear maps.
Standard_EXPORT virtual void clear();
//! Method to add point, normal to surface in this point and face for which point computed.
//! @param[in] thePoint 3D point on the surface
//! @param[in] theNorm surface normal at this point
//! @param[in] theUV surface UV parameters
//! @param[in] theFace surface (face) definition
Standard_EXPORT virtual void addPoint (const gp_Pnt& thePoint,
const gp_Vec& theNorm,
const gp_Pnt2d& theUV,
const TopoDS_Shape& theFace) = 0;
protected:
TopoDS_Shape myShape;
Standard_Real myDist;
Standard_Real myTol;
TopTools_DataMapOfShapeReal myFaceArea;
TopTools_DataMapOfShapeInteger myFacePoints;
Standard_Integer myNbPoints;
};
#endif // _BRepLib_PointCloudShape_HeaderFile

View File

@@ -1,83 +0,0 @@
// Copyright (c) 2021 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 <BRepLib_ToolTriangulatedShape.hxx>
#include <BRep_Tool.hxx>
#include <GeomLib.hxx>
#include <Poly.hxx>
#include <Poly_Connect.hxx>
#include <Precision.hxx>
#include <TopLoc_Location.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Face.hxx>
// =======================================================================
// function : ComputeNormals
// purpose :
// =======================================================================
void BRepLib_ToolTriangulatedShape::ComputeNormals (const TopoDS_Face& theFace,
const Handle(Poly_Triangulation)& theTris,
Poly_Connect& thePolyConnect)
{
if (theTris.IsNull()
|| theTris->HasNormals())
{
return;
}
// take in face the surface location
const TopoDS_Face aZeroFace = TopoDS::Face (theFace.Located (TopLoc_Location()));
Handle(Geom_Surface) aSurf = BRep_Tool::Surface (aZeroFace);
if (!theTris->HasUVNodes() || aSurf.IsNull())
{
// compute normals by averaging triangulation normals sharing the same vertex
Poly::ComputeNormals (theTris);
return;
}
const Standard_Real aTol = Precision::Confusion();
Standard_Integer aTri[3];
gp_Dir aNorm;
theTris->AddNormals();
for (Standard_Integer aNodeIter = 1; aNodeIter <= theTris->NbNodes(); ++aNodeIter)
{
// try to retrieve normal from real surface first, when UV coordinates are available
if (GeomLib::NormEstim (aSurf, theTris->UVNode (aNodeIter), aTol, aNorm) > 1)
{
if (thePolyConnect.Triangulation() != theTris)
{
thePolyConnect.Load (theTris);
}
// compute flat normals
gp_XYZ eqPlan (0.0, 0.0, 0.0);
for (thePolyConnect.Initialize (aNodeIter); thePolyConnect.More(); thePolyConnect.Next())
{
theTris->Triangle (thePolyConnect.Value()).Get (aTri[0], aTri[1], aTri[2]);
const gp_XYZ v1 (theTris->Node (aTri[1]).Coord() - theTris->Node (aTri[0]).Coord());
const gp_XYZ v2 (theTris->Node (aTri[2]).Coord() - theTris->Node (aTri[1]).Coord());
const gp_XYZ vv = v1 ^ v2;
const Standard_Real aMod = vv.Modulus();
if (aMod >= aTol)
{
eqPlan += vv / aMod;
}
}
const Standard_Real aModMax = eqPlan.Modulus();
aNorm = (aModMax > aTol) ? gp_Dir (eqPlan) : gp::DZ();
}
theTris->SetNormal (aNodeIter, aNorm);
}
}

View File

@@ -1,50 +0,0 @@
// Copyright (c) 2021 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 _BrepLib_ToolTriangulatedShape_HeaderFile
#define _BrepLib_ToolTriangulatedShape_HeaderFile
#include <Poly_Connect.hxx>
#include <Poly_Triangulation.hxx>
class TopoDS_Face;
class Poly_Triangulation;
//! Provides methods for calculating normals to Poly_Triangulation of TopoDS_Face.
class BRepLib_ToolTriangulatedShape
{
public:
//! Computes nodal normals for Poly_Triangulation structure using UV coordinates and surface.
//! Does nothing if triangulation already defines normals.
//! @param[in] theFace the face
//! @param[in] theTris the definition of a face triangulation
static void ComputeNormals (const TopoDS_Face& theFace,
const Handle(Poly_Triangulation)& theTris)
{
Poly_Connect aPolyConnect;
ComputeNormals (theFace, theTris, aPolyConnect);
}
//! Computes nodal normals for Poly_Triangulation structure using UV coordinates and surface.
//! Does nothing if triangulation already defines normals.
//! @param[in] theFace the face
//! @param[in] theTris the definition of a face triangulation
//! @param[in,out] thePolyConnect optional, initialized tool for exploring triangulation
Standard_EXPORT static void ComputeNormals (const TopoDS_Face& theFace,
const Handle(Poly_Triangulation)& theTris,
Poly_Connect& thePolyConnect);
};
#endif

View File

@@ -30,12 +30,8 @@ BRepLib_MakeVertex.hxx
BRepLib_MakeWire.cxx
BRepLib_MakeWire.hxx
BRepLib_MakeWire_1.cxx
BRepLib_PointCloudShape.hxx
BRepLib_PointCloudShape.cxx
BRepLib_ShapeModification.hxx
BRepLib_ShellError.hxx
BRepLib_ToolTriangulatedShape.hxx
BRepLib_ToolTriangulatedShape.cxx
BRepLib_ValidateEdge.cxx
BRepLib_ValidateEdge.hxx
BRepLib_WireError.hxx

View File

@@ -48,8 +48,7 @@ BRepMesh_IncrementalMesh::BRepMesh_IncrementalMesh( const TopoDS_Shape& theSh
const Standard_Real theLinDeflection,
const Standard_Boolean isRelative,
const Standard_Real theAngDeflection,
const Standard_Boolean isInParallel,
const Message_ProgressRange& theRange)
const Standard_Boolean isInParallel)
: myModified(Standard_False),
myStatus(IMeshData_NoError)
{
@@ -59,7 +58,7 @@ BRepMesh_IncrementalMesh::BRepMesh_IncrementalMesh( const TopoDS_Shape& theSh
myParameters.InParallel = isInParallel;
myShape = theShape;
Perform(theRange);
Perform();
}
//=======================================================================

View File

@@ -43,8 +43,7 @@ public: //! @name mesher API
const Standard_Real theLinDeflection,
const Standard_Boolean isRelative = Standard_False,
const Standard_Real theAngDeflection = 0.5,
const Standard_Boolean isInParallel = Standard_False,
const Message_ProgressRange& theRange = Message_ProgressRange());
const Standard_Boolean isInParallel = Standard_False);
//! Constructor.
//! Automatically calls method Perform.

View File

@@ -18,7 +18,6 @@
#include <DrawTrSurf.hxx>
#include <Message.hxx>
#include <Message_PrinterOStream.hxx>
#include <Message_PrinterSystemLog.hxx>
#include <NCollection_IndexedMap.hxx>
#include <OSD.hxx>
#include <OSD_Thread.hxx>

View File

@@ -1,4 +0,0 @@
RWPly_CafWriter.cxx
RWPly_CafWriter.hxx
RWPly_PlyWriterContext.cxx
RWPly_PlyWriterContext.hxx

View File

@@ -1,302 +0,0 @@
// Copyright (c) 2022 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 <RWPly_CafWriter.hxx>
#include <Message.hxx>
#include <Message_LazyProgressScope.hxx>
#include <OSD_Path.hxx>
#include <RWMesh_FaceIterator.hxx>
#include <RWMesh_MaterialMap.hxx>
#include <RWPly_PlyWriterContext.hxx>
#include <Standard_CLocaleSentry.hxx>
#include <TDocStd_Document.hxx>
#include <TDataStd_Name.hxx>
#include <XCAFDoc_DocumentTool.hxx>
#include <XCAFDoc_ShapeTool.hxx>
#include <XCAFPrs_DocumentExplorer.hxx>
IMPLEMENT_STANDARD_RTTIEXT(RWPly_CafWriter, Standard_Transient)
//================================================================
// Function : Constructor
// Purpose :
//================================================================
RWPly_CafWriter::RWPly_CafWriter (const TCollection_AsciiString& theFile)
: myFile (theFile),
myIsDoublePrec (false),
myHasNormals (true),
myHasColors (true),
myHasTexCoords (false),
myHasPartId (true),
myHasFaceId (false)
{
//
}
//================================================================
// Function : Destructor
// Purpose :
//================================================================
RWPly_CafWriter::~RWPly_CafWriter()
{
//
}
//================================================================
// Function : toSkipFaceMesh
// Purpose :
//================================================================
Standard_Boolean RWPly_CafWriter::toSkipFaceMesh (const RWMesh_FaceIterator& theFaceIter)
{
return theFaceIter.IsEmptyMesh();
}
// =======================================================================
// function : Perform
// purpose :
// =======================================================================
bool RWPly_CafWriter::Perform (const Handle(TDocStd_Document)& theDocument,
const TColStd_IndexedDataMapOfStringString& theFileInfo,
const Message_ProgressRange& theProgress)
{
TDF_LabelSequence aRoots;
Handle(XCAFDoc_ShapeTool) aShapeTool = XCAFDoc_DocumentTool::ShapeTool (theDocument->Main());
aShapeTool->GetFreeShapes (aRoots);
return Perform (theDocument, aRoots, NULL, theFileInfo, theProgress);
}
// =======================================================================
// function : Perform
// purpose :
// =======================================================================
bool RWPly_CafWriter::Perform (const Handle(TDocStd_Document)& theDocument,
const TDF_LabelSequence& theRootLabels,
const TColStd_MapOfAsciiString* theLabelFilter,
const TColStd_IndexedDataMapOfStringString& theFileInfo,
const Message_ProgressRange& theProgress)
{
TCollection_AsciiString aFolder, aFileName, aFullFileNameBase, aShortFileNameBase, aFileExt;
OSD_Path::FolderAndFileFromPath (myFile, aFolder, aFileName);
OSD_Path::FileNameAndExtension (aFileName, aShortFileNameBase, aFileExt);
Standard_Real aLengthUnit = 1.;
if (XCAFDoc_DocumentTool::GetLengthUnit(theDocument, aLengthUnit))
{
myCSTrsf.SetInputLengthUnit(aLengthUnit);
}
if (theRootLabels.IsEmpty()
|| (theLabelFilter != NULL && theLabelFilter->IsEmpty()))
{
Message::SendFail ("Nothing to export into PLY file");
return false;
}
Standard_Integer aNbNodesAll = 0, aNbElemsAll = 0;
Standard_Real aNbPEntities = 0; // steps for progress range
for (XCAFPrs_DocumentExplorer aDocExplorer (theDocument, theRootLabels, XCAFPrs_DocumentExplorerFlags_OnlyLeafNodes);
aDocExplorer.More(); aDocExplorer.Next())
{
const XCAFPrs_DocumentNode& aDocNode = aDocExplorer.Current();
if (theLabelFilter != NULL
&& !theLabelFilter->Contains (aDocNode.Id))
{
continue;
}
for (RWMesh_FaceIterator aFaceIter (aDocNode.RefLabel, aDocNode.Location, true, aDocNode.Style); aFaceIter.More(); aFaceIter.Next())
{
if (toSkipFaceMesh (aFaceIter))
{
continue;
}
addFaceInfo (aFaceIter, aNbNodesAll, aNbElemsAll);
aNbPEntities += aNbNodesAll + aNbElemsAll;
}
}
if (aNbNodesAll == 0)
{
Message::SendFail ("No mesh data to save");
return false;
}
Standard_CLocaleSentry aLocaleSentry;
RWPly_PlyWriterContext aPlyCtx;
aPlyCtx.SetDoublePrecision (myIsDoublePrec);
aPlyCtx.SetNormals (myHasNormals);
aPlyCtx.SetColors (myHasColors);
aPlyCtx.SetTexCoords (myHasTexCoords);
aPlyCtx.SetSurfaceId (myHasPartId || myHasFaceId);
if (!aPlyCtx.Open (myFile)
|| !aPlyCtx.WriteHeader (aNbNodesAll, aNbElemsAll, theFileInfo))
{
return false;
}
// simple global progress sentry
const Standard_Real aPatchStep = 2048.0;
Message_LazyProgressScope aPSentry (theProgress, "PLY export", aNbPEntities, aPatchStep);
bool isDone = true;
for (Standard_Integer aStepIter = 0; aStepIter < 2; ++aStepIter)
{
aPlyCtx.SetSurfaceId (0);
for (XCAFPrs_DocumentExplorer aDocExplorer (theDocument, theRootLabels, XCAFPrs_DocumentExplorerFlags_OnlyLeafNodes);
aDocExplorer.More() && !aPSentry.IsAborted(); aDocExplorer.Next())
{
const XCAFPrs_DocumentNode& aDocNode = aDocExplorer.Current();
if (theLabelFilter != NULL
&& !theLabelFilter->Contains (aDocNode.Id))
{
continue;
}
if (myHasPartId)
{
aPlyCtx.SetSurfaceId (aPlyCtx.SurfaceId() + 1);
}
if (!writeShape (aPlyCtx, aPSentry, aStepIter, aDocNode.RefLabel, aDocNode.Location, aDocNode.Style))
{
isDone = false;
break;
}
}
}
const bool isClosed = aPlyCtx.Close();
if (isDone && !isClosed)
{
Message::SendFail (TCollection_AsciiString ("Failed to write PLY file\n") + myFile);
return false;
}
return isDone && !aPSentry.IsAborted();
}
// =======================================================================
// function : addFaceInfo
// purpose :
// =======================================================================
void RWPly_CafWriter::addFaceInfo (const RWMesh_FaceIterator& theFace,
Standard_Integer& theNbNodes,
Standard_Integer& theNbElems)
{
theNbNodes += theFace.NbNodes();
theNbElems += theFace.NbTriangles();
}
// =======================================================================
// function : writeShape
// purpose :
// =======================================================================
bool RWPly_CafWriter::writeShape (RWPly_PlyWriterContext& theWriter,
Message_LazyProgressScope& thePSentry,
const Standard_Integer theWriteStep,
const TDF_Label& theLabel,
const TopLoc_Location& theParentTrsf,
const XCAFPrs_Style& theParentStyle)
{
for (RWMesh_FaceIterator aFaceIter (theLabel, theParentTrsf, true, theParentStyle); aFaceIter.More() && !thePSentry.IsAborted(); aFaceIter.Next())
{
if (toSkipFaceMesh (aFaceIter))
{
continue;
}
if (theWriteStep == 0
&& !writeNodes (theWriter, thePSentry, aFaceIter))
{
return false;
}
if (theWriteStep == 1
&& !writeIndices (theWriter, thePSentry, aFaceIter))
{
return false;
}
}
return true;
}
// =======================================================================
// function : writeNodes
// purpose :
// =======================================================================
bool RWPly_CafWriter::writeNodes (RWPly_PlyWriterContext& theWriter,
Message_LazyProgressScope& thePSentry,
const RWMesh_FaceIterator& theFace)
{
const Standard_Integer aNodeUpper = theFace.NodeUpper();
Graphic3d_Vec3 aNormVec;
Graphic3d_Vec2 aTexVec;
Graphic3d_Vec4ub aColorVec (255);
if (theFace.HasFaceColor())
{
//Graphic3d_Vec4 aColorF = Quantity_ColorRGBA::Convert_LinearRGB_To_sRGB (theFace.FaceColor());
Graphic3d_Vec4 aColorF = theFace.FaceColor();
aColorVec.SetValues ((unsigned char )int(aColorF.r() * 255.0f),
(unsigned char )int(aColorF.g() * 255.0f),
(unsigned char )int(aColorF.b() * 255.0f),
(unsigned char )int(aColorF.a() * 255.0f));
}
for (Standard_Integer aNodeIter = theFace.NodeLower(); aNodeIter <= aNodeUpper && thePSentry.More(); ++aNodeIter, thePSentry.Next())
{
gp_XYZ aNode = theFace.NodeTransformed (aNodeIter).XYZ();
myCSTrsf.TransformPosition (aNode);
if (theFace.HasNormals())
{
gp_Dir aNorm = theFace.NormalTransformed (aNodeIter);
aNormVec.SetValues ((float )aNorm.X(), (float )aNorm.Y(), (float )aNorm.Z());
myCSTrsf.TransformNormal (aNormVec);
}
if (theFace.HasTexCoords())
{
const gp_Pnt2d aUV = theFace.NodeTexCoord (aNodeIter);
aTexVec.SetValues ((float )aUV.X(), (float )aUV.Y());
}
if (!theWriter.WriteVertex (aNode, aNormVec, aTexVec, aColorVec))
{
return false;
}
}
return true;
}
// =======================================================================
// function : writeIndices
// purpose :
// =======================================================================
bool RWPly_CafWriter::writeIndices (RWPly_PlyWriterContext& theWriter,
Message_LazyProgressScope& thePSentry,
const RWMesh_FaceIterator& theFace)
{
if (myHasFaceId)
{
theWriter.SetSurfaceId (theWriter.SurfaceId() + 1);
}
const Standard_Integer anElemLower = theFace.ElemLower();
const Standard_Integer anElemUpper = theFace.ElemUpper();
for (Standard_Integer anElemIter = anElemLower; anElemIter <= anElemUpper && thePSentry.More(); ++anElemIter, thePSentry.Next())
{
const Poly_Triangle aTri = theFace.TriangleOriented (anElemIter);
if (!theWriter.WriteTriangle (Graphic3d_Vec3i (aTri(1), aTri(2), aTri(3)) - Graphic3d_Vec3i (anElemLower)))
{
return false;
}
}
theWriter.SetVertexOffset (theWriter.VertexOffset() + theFace.NbNodes());
return true;
}

View File

@@ -1,198 +0,0 @@
// Copyright (c) 2022 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 _RWPly_CafWriter_HeaderFiler
#define _RWPly_CafWriter_HeaderFiler
#include <TColStd_IndexedDataMapOfStringString.hxx>
#include <TColStd_MapOfAsciiString.hxx>
#include <TDF_LabelSequence.hxx>
#include <TopTools_ShapeMapHasher.hxx>
#include <RWMesh_CoordinateSystemConverter.hxx>
#include <XCAFPrs_Style.hxx>
#include <memory>
class Message_ProgressRange;
class RWMesh_FaceIterator;
class TDocStd_Document;
class Message_LazyProgressScope;
class RWPly_PlyWriterContext;
//! PLY writer context from XCAF document.
class RWPly_CafWriter : public Standard_Transient
{
DEFINE_STANDARD_RTTIEXT(RWPly_CafWriter, Standard_Transient)
public:
//! Main constructor.
//! @param[in] theFile path to output PLY file
Standard_EXPORT RWPly_CafWriter (const TCollection_AsciiString& theFile);
//! Destructor.
Standard_EXPORT virtual ~RWPly_CafWriter();
//! Return transformation from OCCT to PLY coordinate system.
const RWMesh_CoordinateSystemConverter& CoordinateSystemConverter() const { return myCSTrsf; }
//! Return transformation from OCCT to PLY coordinate system.
RWMesh_CoordinateSystemConverter& ChangeCoordinateSystemConverter() { return myCSTrsf; }
//! Set transformation from OCCT to PLY coordinate system.
void SetCoordinateSystemConverter (const RWMesh_CoordinateSystemConverter& theConverter) { myCSTrsf = theConverter; }
//! Return default material definition to be used for nodes with only color defined.
const XCAFPrs_Style& DefaultStyle() const { return myDefaultStyle; }
//! Set default material definition to be used for nodes with only color defined.
void SetDefaultStyle (const XCAFPrs_Style& theStyle) { myDefaultStyle = theStyle; }
public:
//! Return TRUE if vertex position should be stored with double floating point precision; FALSE by default.
bool IsDoublePrecision() const { return myIsDoublePrec; }
//! Set if vertex position should be stored with double floating point precision.
void SetDoublePrecision (bool theDoublePrec) { myIsDoublePrec = theDoublePrec; }
//! Return TRUE if normals should be written; TRUE by default.
bool HasNormals() const { return myHasNormals; }
//! Set if normals are defined.
void SetNormals (const bool theHasNormals) { myHasNormals = theHasNormals; }
//! Return TRUE if UV / texture coordinates should be written; FALSE by default.
bool HasTexCoords() const { return myHasTexCoords; }
//! Set if UV / texture coordinates should be written.
void SetTexCoords (const bool theHasTexCoords) { myHasTexCoords = theHasTexCoords; }
//! Return TRUE if point colors should be written; TRUE by default.
bool HasColors() const { return myHasColors; }
//! Set if point colors should be written.
void SetColors (bool theToWrite) { myHasColors = theToWrite; }
//! Return TRUE if part Id should be written as element attribute; TRUE by default.
bool HasPartId() const { return myHasPartId; }
//! Set if part Id should be written as element attribute; FALSE by default.
//! Cannot be combined with HasFaceId().
void SetPartId (bool theSurfId)
{
myHasPartId = theSurfId;
myHasFaceId = myHasFaceId && !myHasPartId;
}
//! Return TRUE if face Id should be written as element attribute; FALSE by default.
bool HasFaceId() const { return myHasFaceId; }
//! Set if face Id should be written as element attribute; FALSE by default.
//! Cannot be combined with HasPartId().
void SetFaceId (bool theSurfId)
{
myHasFaceId = theSurfId;
myHasPartId = myHasPartId && !myHasFaceId;
}
public:
//! Write PLY file and associated MTL material file.
//! Triangulation data should be precomputed within shapes!
//! @param[in] theDocument input document
//! @param[in] theRootLabels list of root shapes to export
//! @param[in] theLabelFilter optional filter with document nodes to export,
//! with keys defined by XCAFPrs_DocumentExplorer::DefineChildId() and filled recursively
//! (leaves and parent assembly nodes at all levels);
//! when not NULL, all nodes not included into the map will be ignored
//! @param[in] theFileInfo map with file metadata to put into PLY header section
//! @param[in] theProgress optional progress indicator
//! @return FALSE on file writing failure
Standard_EXPORT virtual bool Perform (const Handle(TDocStd_Document)& theDocument,
const TDF_LabelSequence& theRootLabels,
const TColStd_MapOfAsciiString* theLabelFilter,
const TColStd_IndexedDataMapOfStringString& theFileInfo,
const Message_ProgressRange& theProgress);
//! Write PLY file and associated MTL material file.
//! Triangulation data should be precomputed within shapes!
//! @param[in] theDocument input document
//! @param[in] theFileInfo map with file metadata to put into PLY header section
//! @param[in] theProgress optional progress indicator
//! @return FALSE on file writing failure
Standard_EXPORT virtual bool Perform (const Handle(TDocStd_Document)& theDocument,
const TColStd_IndexedDataMapOfStringString& theFileInfo,
const Message_ProgressRange& theProgress);
protected:
//! Return TRUE if face mesh should be skipped (e.g. because it is invalid or empty).
Standard_EXPORT virtual Standard_Boolean toSkipFaceMesh (const RWMesh_FaceIterator& theFaceIter);
//! Collect face triangulation info.
//! @param[in] theFace face to process
//! @param[in,out] theNbNodes overall number of triangulation nodes (should be appended)
//! @param[in,out] theNbElems overall number of triangulation elements (should be appended)
Standard_EXPORT virtual void addFaceInfo (const RWMesh_FaceIterator& theFace,
Standard_Integer& theNbNodes,
Standard_Integer& theNbElems);
//! Write the shape.
//! @param[in] theWriter PLY writer context
//! @param[in] thePSentry progress sentry
//! @param[in] theWriteStep export step, 0 for vertex attributes, 1 for elements
//! @param[in] theLabel document label to process
//! @param[in] theParentTrsf parent node transformation
//! @param[in] theParentStyle parent node style
Standard_EXPORT virtual bool writeShape (RWPly_PlyWriterContext& theWriter,
Message_LazyProgressScope& thePSentry,
const Standard_Integer theWriteStep,
const TDF_Label& theLabel,
const TopLoc_Location& theParentTrsf,
const XCAFPrs_Style& theParentStyle);
//! Write face triangle vertices and attributes.
//! @param[in] theWriter PLY writer context
//! @param[in] thePSentry progress sentry
//! @param[in] theFace current face
//! @return FALSE on writing file error
Standard_EXPORT virtual bool writeNodes (RWPly_PlyWriterContext& theWriter,
Message_LazyProgressScope& thePSentry,
const RWMesh_FaceIterator& theFace);
//! Write face triangles indices.
//! @param[in] theWriter PLY writer context
//! @param[in] thePSentry progress sentry
//! @param[in] theFace current face
//! @return FALSE on writing file error
Standard_EXPORT virtual bool writeIndices (RWPly_PlyWriterContext& theWriter,
Message_LazyProgressScope& thePSentry,
const RWMesh_FaceIterator& theFace);
protected:
TCollection_AsciiString myFile; //!< output PLY file
RWMesh_CoordinateSystemConverter myCSTrsf; //!< transformation from OCCT to PLY coordinate system
XCAFPrs_Style myDefaultStyle; //!< default material definition to be used for nodes with only color defined
Standard_Boolean myIsDoublePrec;
Standard_Boolean myHasNormals;
Standard_Boolean myHasColors;
Standard_Boolean myHasTexCoords;
Standard_Boolean myHasPartId;
Standard_Boolean myHasFaceId;
};
#endif // _RWPly_CafWriter_HeaderFiler

View File

@@ -1,324 +0,0 @@
// Copyright (c) 2022 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 <RWPly_PlyWriterContext.hxx>
#include <Message.hxx>
#include <NCollection_IndexedMap.hxx>
#include <OSD_FileSystem.hxx>
// =======================================================================
// function : splitLines
// purpose :
// =======================================================================
static void splitLines (const TCollection_AsciiString& theString,
NCollection_IndexedMap<TCollection_AsciiString>& theLines)
{
if (theString.IsEmpty())
{
return;
}
Standard_Integer aLineFrom = 1;
for (Standard_Integer aCharIter = 1;; ++aCharIter)
{
const char aChar = theString.Value (aCharIter);
if (aChar != '\r'
&& aChar != '\n'
&& aCharIter != theString.Length())
{
continue;
}
if (aLineFrom != aCharIter)
{
TCollection_AsciiString aLine = theString.SubString (aLineFrom, aCharIter);
aLine.RightAdjust();
theLines.Add (aLine);
}
if (aCharIter == theString.Length())
{
break;
}
else if (aChar == '\r'
&& theString.Value (aCharIter + 1) == '\n')
{
// CRLF
++aCharIter;
}
aLineFrom = aCharIter + 1;
}
}
// ================================================================
// Function : RWPly_PlyWriterContext
// Purpose :
// ================================================================
RWPly_PlyWriterContext::RWPly_PlyWriterContext()
: myNbHeaderVerts (0),
myNbHeaderElems (0),
myNbVerts (0),
myNbElems (0),
mySurfId (0),
myVertOffset (0),
myIsDoublePrec (false),
myHasNormals (false),
myHasColors (false),
myHasTexCoords (false),
myHasSurfId (false)
{
//
}
// ================================================================
// Function : ~RWPly_PlyWriterContext
// Purpose :
// ================================================================
RWPly_PlyWriterContext::~RWPly_PlyWriterContext()
{
Close();
}
// ================================================================
// Function : Open
// Purpose :
// ================================================================
bool RWPly_PlyWriterContext::Open (const TCollection_AsciiString& theName,
const std::shared_ptr<std::ostream>& theStream)
{
myName = theName;
myNbHeaderVerts = myNbHeaderElems = 0;
myNbVerts = myNbElems = 0;
if (theStream.get() != nullptr)
{
myStream = theStream;
return true;
}
const Handle(OSD_FileSystem)& aFileSystem = OSD_FileSystem::DefaultFileSystem();
myStream = aFileSystem->OpenOStream (theName, std::ios::out | std::ios::binary);
if (myStream.get() == NULL || !myStream->good())
{
myStream.reset();
Message::SendFail() << "Error: file cannot be created\n" << theName;
return false;
}
return true;
}
// ================================================================
// Function : Close
// Purpose :
// ================================================================
bool RWPly_PlyWriterContext::Close (bool theIsAborted)
{
if (myStream.get() == nullptr)
{
return false;
}
myStream->flush();
bool aResult = myStream->good();
if (!aResult)
{
Message::SendFail() << "Error: file cannot be written\n" << myName;
}
else if (!theIsAborted)
{
if (myNbVerts != myNbHeaderVerts)
{
Message::SendFail() << "Error: written less number of vertices (" << myNbVerts << ") than specified in PLY header (" << myNbHeaderVerts << ")";
}
else if (myNbElems != myNbHeaderElems)
{
Message::SendFail() << "Error: written less number of elements (" << myNbElems << ") than specified in PLY header (" << myNbHeaderElems << ")";
}
}
myStream.reset();
return aResult;
}
// ================================================================
// Function : WriteHeader
// Purpose :
// ================================================================
bool RWPly_PlyWriterContext::WriteHeader (const Standard_Integer theNbNodes,
const Standard_Integer theNbElems,
const TColStd_IndexedDataMapOfStringString& theFileInfo)
{
if (myStream.get() == nullptr)
{
return false;
}
myNbHeaderVerts = theNbNodes;
myNbHeaderElems = theNbElems;
*myStream << "ply\n"
"format ascii 1.0\n"
"comment Exported by Open CASCADE Technology [dev.opencascade.org]\n";
for (TColStd_IndexedDataMapOfStringString::Iterator aKeyValueIter (theFileInfo); aKeyValueIter.More(); aKeyValueIter.Next())
{
NCollection_IndexedMap<TCollection_AsciiString> aKeyLines, aValLines;
splitLines (aKeyValueIter.Key(), aKeyLines);
splitLines (aKeyValueIter.Value(), aValLines);
for (Standard_Integer aLineIter = 1; aLineIter <= aKeyLines.Extent(); ++aLineIter)
{
const TCollection_AsciiString& aLine = aKeyLines.FindKey (aLineIter);
*myStream << (aLineIter > 1 ? "\n" : "") << "comment " << aLine;
}
*myStream << (!aKeyLines.IsEmpty() ? ":" : "comment ");
for (Standard_Integer aLineIter = 1; aLineIter <= aValLines.Extent(); ++aLineIter)
{
const TCollection_AsciiString& aLine = aValLines.FindKey (aLineIter);
*myStream << (aLineIter > 1 ? "\n" : "") << "comment " << aLine;
}
*myStream << "\n";
}
*myStream << "element vertex " << theNbNodes<< "\n";
if (myIsDoublePrec)
{
*myStream << "property double x\n"
"property double y\n"
"property double z\n";
}
else
{
*myStream << "property float x\n"
"property float y\n"
"property float z\n";
}
if (myHasNormals)
{
*myStream << "property float nx\n"
"property float ny\n"
"property float nz\n";
}
if (myHasTexCoords)
{
*myStream << "property float s\n"
"property float t\n";
}
if (myHasColors)
{
*myStream << "property uchar red\n"
"property uchar green\n"
"property uchar blue\n";
}
if (theNbElems > 0)
{
*myStream << "element face " << theNbElems << "\n"
"property list uchar uint vertex_indices\n";
if (myHasSurfId)
{
*myStream << "property uint SurfaceID\n";
}
}
*myStream << "end_header\n";
return myStream->good();
}
// ================================================================
// Function : WriteVertex
// Purpose :
// ================================================================
bool RWPly_PlyWriterContext::WriteVertex (const gp_Pnt& thePoint,
const Graphic3d_Vec3& theNorm,
const Graphic3d_Vec2& theUV,
const Graphic3d_Vec4ub& theColor)
{
if (myStream.get() == nullptr)
{
return false;
}
if (myIsDoublePrec)
{
*myStream << (double )thePoint.X() << " " << (double )thePoint.Y() << " " << (double )thePoint.Z();
}
else
{
*myStream << (float )thePoint.X() << " " << (float )thePoint.Y() << " " << (float )thePoint.Z();
}
if (myHasNormals)
{
*myStream << " " << (float )theNorm.x() << " " << (float )theNorm.y() << " " << (float )theNorm.z();
}
if (myHasTexCoords)
{
*myStream << " " << (float )theUV.x() << " " << (float )theUV.y();
}
if (myHasColors)
{
*myStream << " " << (int )theColor.r() << " " << (int )theColor.g() << " " << (int )theColor.b();
}
*myStream << "\n";
if (++myNbVerts > myNbHeaderVerts)
{
throw Standard_OutOfRange ("RWPly_PlyWriterContext::WriteVertex() - number of vertices is greater than defined");
}
return myStream->good();
}
// ================================================================
// Function : WriteTriangle
// Purpose :
// ================================================================
bool RWPly_PlyWriterContext::WriteTriangle (const Graphic3d_Vec3i& theTri)
{
if (myStream.get() == nullptr)
{
return false;
}
const Graphic3d_Vec3i aTri = Graphic3d_Vec3i(myVertOffset) + theTri;
*myStream << "3 " << aTri[0] << " " << aTri[1] << " " << aTri[2];
if (myHasSurfId)
{
*myStream << " " << mySurfId;
}
*myStream << "\n";
if (++myNbElems > myNbHeaderElems)
{
throw Standard_OutOfRange ("RWPly_PlyWriterContext::WriteTriangle() - number of elements is greater than defined");
}
return myStream->good();
}
// ================================================================
// Function : WriteQuad
// Purpose :
// ================================================================
bool RWPly_PlyWriterContext::WriteQuad (const Graphic3d_Vec4i& theQuad)
{
if (myStream.get() == nullptr)
{
return false;
}
const Graphic3d_Vec4i aQuad = Graphic3d_Vec4i(myVertOffset) + theQuad;
*myStream << "4 " << aQuad[0] << " " << aQuad[1] << " " << aQuad[2] << " " << aQuad[3];
if (myHasSurfId)
{
*myStream << " " << mySurfId;
}
*myStream << "\n";
if (++myNbElems > myNbHeaderElems)
{
throw Standard_OutOfRange ("RWPly_PlyWriterContext::WriteQuad() - number of elements is greater than defined");
}
return myStream->good();
}

View File

@@ -1,142 +0,0 @@
// Copyright (c) 2022 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 _RWPly_PlyWriterContext_HeaderFiler
#define _RWPly_PlyWriterContext_HeaderFiler
#include <Graphic3d_Vec.hxx>
#include <gp_Pnt.hxx>
#include <TCollection_AsciiString.hxx>
#include <TColStd_IndexedDataMapOfStringString.hxx>
#include <memory>
//! Auxiliary low-level tool writing PLY file.
class RWPly_PlyWriterContext
{
public:
//! Empty constructor.
Standard_EXPORT RWPly_PlyWriterContext();
//! Destructor, will emit error message if file was not closed.
Standard_EXPORT ~RWPly_PlyWriterContext();
public: //! @name vertex attributes parameters
//! Return TRUE if vertex position should be stored with double floating point precision; FALSE by default.
bool IsDoublePrecision() const { return myIsDoublePrec; }
//! Set if vertex position should be stored with double floating point precision.
void SetDoublePrecision (bool theDoublePrec) { myIsDoublePrec = theDoublePrec; }
//! Return TRUE if normals should be written as vertex attribute; FALSE by default.
bool HasNormals() const { return myHasNormals; }
//! Set if normals should be written.
void SetNormals (const bool theHasNormals) { myHasNormals = theHasNormals; }
//! Return TRUE if UV / texture coordinates should be written as vertex attribute; FALSE by default.
bool HasTexCoords() const { return myHasTexCoords; }
//! Set if UV / texture coordinates should be written.
void SetTexCoords (const bool theHasTexCoords) { myHasTexCoords = theHasTexCoords; }
//! Return TRUE if point colors should be written as vertex attribute; FALSE by default.
bool HasColors() const { return myHasColors; }
//! Set if point colors should be written.
void SetColors (bool theToWrite) { myHasColors = theToWrite; }
public: //! @name element attributes parameters
//! Return TRUE if surface Id should be written as element attribute; FALSE by default.
bool HasSurfaceId() const { return myHasSurfId; }
//! Set if surface Id should be written as element attribute; FALSE by default.
void SetSurfaceId (bool theSurfId) { myHasSurfId = theSurfId; }
public: //! @name writing into file
//! Return TRUE if file has been opened.
bool IsOpened() const { return myStream.get() != nullptr; }
//! Open file for writing.
Standard_EXPORT bool Open (const TCollection_AsciiString& theName,
const std::shared_ptr<std::ostream>& theStream = std::shared_ptr<std::ostream>());
//! Write the header.
//! @param[in] theNbNodes number of vertex nodes
//! @param[in] theNbElems number of mesh elements
//! @param[in] theFileInfo optional comments
Standard_EXPORT bool WriteHeader (const Standard_Integer theNbNodes,
const Standard_Integer theNbElems,
const TColStd_IndexedDataMapOfStringString& theFileInfo);
//! Write single point with all attributes.
//! @param[in] thePoint 3D point coordinates
//! @param[in] theNorm surface normal direction at the point
//! @param[in] theUV surface/texture UV coordinates
//! @param[in] theColor RGB color values
Standard_EXPORT bool WriteVertex (const gp_Pnt& thePoint,
const Graphic3d_Vec3& theNorm,
const Graphic3d_Vec2& theUV,
const Graphic3d_Vec4ub& theColor);
//! Return number of written vertices.
Standard_Integer NbWrittenVertices() const { return myNbVerts; }
//! Return vertex offset to be applied to element indices; 0 by default.
Standard_Integer VertexOffset() const { return myVertOffset; }
//! Set vertex offset to be applied to element indices.
void SetVertexOffset (Standard_Integer theOffset) { myVertOffset = theOffset; }
//! Return surface id to write with element; 0 by default.
Standard_Integer SurfaceId() const { return mySurfId; }
//! Set surface id to write with element.
void SetSurfaceId (Standard_Integer theSurfId) { mySurfId = theSurfId; }
//! Writing a triangle.
Standard_EXPORT bool WriteTriangle (const Graphic3d_Vec3i& theTri);
//! Writing a quad.
Standard_EXPORT bool WriteQuad (const Graphic3d_Vec4i& theQuad);
//! Return number of written elements.
Standard_Integer NbWrittenElements() const { return myNbElems; }
//! Correctly close the file.
//! @return FALSE in case of writing error
Standard_EXPORT bool Close (bool theIsAborted = false);
private:
std::shared_ptr<std::ostream> myStream;
TCollection_AsciiString myName;
Standard_Integer myNbHeaderVerts;
Standard_Integer myNbHeaderElems;
Standard_Integer myNbVerts;
Standard_Integer myNbElems;
Standard_Integer mySurfId;
Standard_Integer myVertOffset;
bool myIsDoublePrec;
bool myHasNormals;
bool myHasColors;
bool myHasTexCoords;
bool myHasSurfId;
};
#endif // _RWPly_PlyWriterContext_HeaderFiler

View File

@@ -147,6 +147,12 @@ Handle(Poly_Triangulation) RWStl::ReadFile (const OSD_Path& theFile,
Handle(Poly_Triangulation) RWStl::ReadBinary (const OSD_Path& theFile,
const Message_ProgressRange& theProgress)
{
OSD_File aFile(theFile);
if (!aFile.Exists())
{
return Handle(Poly_Triangulation)();
}
TCollection_AsciiString aPath;
theFile.SystemName (aPath);
@@ -173,24 +179,31 @@ Handle(Poly_Triangulation) RWStl::ReadBinary (const OSD_Path& theFile,
Handle(Poly_Triangulation) RWStl::ReadAscii (const OSD_Path& theFile,
const Message_ProgressRange& theProgress)
{
TCollection_AsciiString aPath;
theFile.SystemName (aPath);
const Handle(OSD_FileSystem)& aFileSystem = OSD_FileSystem::DefaultFileSystem();
std::shared_ptr<std::istream> aStream = aFileSystem->OpenIStream (aPath, std::ios::in | std::ios::binary);
if (aStream.get() == NULL)
OSD_File aFile (theFile);
if (!aFile.Exists())
{
return Handle(Poly_Triangulation)();
}
TCollection_AsciiString aPath;
theFile.SystemName (aPath);
std::filebuf aBuf;
OSD_OpenStream (aBuf, aPath, std::ios::in | std::ios::binary);
if (!aBuf.is_open())
{
return Handle(Poly_Triangulation)();
}
Standard_IStream aStream (&aBuf);
// get length of file to feed progress indicator
aStream->seekg (0, aStream->end);
std::streampos theEnd = aStream->tellg();
aStream->seekg (0, aStream->beg);
aStream.seekg (0, aStream.end);
std::streampos theEnd = aStream.tellg();
aStream.seekg (0, aStream.beg);
Reader aReader;
Standard_ReadLineBuffer aBuffer (THE_BUFFER_SIZE);
if (!aReader.ReadAscii (*aStream, aBuffer, theEnd, theProgress))
if (!aReader.ReadAscii (aStream, aBuffer, theEnd, theProgress))
{
return Handle(Poly_Triangulation)();
}
@@ -338,7 +351,7 @@ Standard_Boolean RWStl::writeBinary (const Handle(Poly_Triangulation)& theMesh,
FILE* theFile,
const Message_ProgressRange& theProgress)
{
char aHeader[80] = "STL Exported by Open CASCADE Technology [dev.opencascade.org]";
char aHeader[80] = "STL Exported by OpenCASCADE [www.opencascade.com]";
if (fwrite (aHeader, 1, 80, theFile) != 80)
{
return Standard_False;

View File

@@ -18,11 +18,24 @@
#include <BRepBndLib.hxx>
#include <BRepMesh_DiscretFactory.hxx>
#include <BRepMesh_DiscretRoot.hxx>
#include <BRepTools.hxx>
#include <BRep_Tool.hxx>
#include <GeomAbs_SurfaceType.hxx>
#include <GeomLib.hxx>
#include <gp_XYZ.hxx>
#include <Poly.hxx>
#include <Poly_Connect.hxx>
#include <Poly_Triangulation.hxx>
#include <Precision.hxx>
#include <Prs3d.hxx>
#include <Prs3d_Drawer.hxx>
#include <TColgp_Array1OfPnt.hxx>
#include <TColgp_Array1OfPnt2d.hxx>
#include <TopAbs_Orientation.hxx>
#include <TopLoc_Location.hxx>
#include <TShort_HArray1OfShortReal.hxx>
#include <TShort_Array1OfShortReal.hxx>
#include <TopExp_Explorer.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Face.hxx>
@@ -119,6 +132,66 @@ Standard_Boolean StdPrs_ToolTriangulatedShape::IsClosed (const TopoDS_Shape& the
}
}
//=======================================================================
//function : ComputeNormals
//purpose :
//=======================================================================
void StdPrs_ToolTriangulatedShape::ComputeNormals (const TopoDS_Face& theFace,
const Handle(Poly_Triangulation)& theTris,
Poly_Connect& thePolyConnect)
{
if (theTris.IsNull()
|| theTris->HasNormals())
{
return;
}
// take in face the surface location
const TopoDS_Face aZeroFace = TopoDS::Face (theFace.Located (TopLoc_Location()));
Handle(Geom_Surface) aSurf = BRep_Tool::Surface (aZeroFace);
if (!theTris->HasUVNodes() || aSurf.IsNull())
{
// compute normals by averaging triangulation normals sharing the same vertex
Poly::ComputeNormals (theTris);
return;
}
const Standard_Real aTol = Precision::Confusion();
Standard_Integer aTri[3];
gp_Dir aNorm;
theTris->AddNormals();
for (Standard_Integer aNodeIter = 1; aNodeIter <= theTris->NbNodes(); ++aNodeIter)
{
// try to retrieve normal from real surface first, when UV coordinates are available
if (GeomLib::NormEstim (aSurf, theTris->UVNode (aNodeIter), aTol, aNorm) > 1)
{
if (thePolyConnect.Triangulation() != theTris)
{
thePolyConnect.Load (theTris);
}
// compute flat normals
gp_XYZ eqPlan (0.0, 0.0, 0.0);
for (thePolyConnect.Initialize (aNodeIter); thePolyConnect.More(); thePolyConnect.Next())
{
theTris->Triangle (thePolyConnect.Value()).Get (aTri[0], aTri[1], aTri[2]);
const gp_XYZ v1 (theTris->Node (aTri[1]).Coord() - theTris->Node (aTri[0]).Coord());
const gp_XYZ v2 (theTris->Node (aTri[2]).Coord() - theTris->Node (aTri[1]).Coord());
const gp_XYZ vv = v1 ^ v2;
const Standard_Real aMod = vv.Modulus();
if (aMod >= aTol)
{
eqPlan += vv / aMod;
}
}
const Standard_Real aModMax = eqPlan.Modulus();
aNorm = (aModMax > aTol) ? gp_Dir (eqPlan) : gp::DZ();
}
theTris->SetNormal (aNodeIter, aNorm);
}
}
//=======================================================================
//function : Normal
//purpose :

View File

@@ -14,13 +14,19 @@
#ifndef _StdPrs_ToolTriangulatedShape_HeaderFile
#define _StdPrs_ToolTriangulatedShape_HeaderFile
#include <BRepLib_ToolTriangulatedShape.hxx>
#include <Poly_Connect.hxx>
#include <Poly_Triangulation.hxx>
#include <Prs3d_Drawer.hxx>
#include <Standard.hxx>
#include <Standard_Macro.hxx>
#include <TColgp_Array1OfDir.hxx>
class TopoDS_Face;
class TopoDS_Shape;
class Prs3d_Drawer;
class Poly_Triangulation;
class StdPrs_ToolTriangulatedShape: public BRepLib_ToolTriangulatedShape
class StdPrs_ToolTriangulatedShape
{
public:
@@ -32,6 +38,26 @@ public:
//! @return true if shape is closed manifold Solid or compound of such Solids. <br>
Standard_EXPORT static Standard_Boolean IsClosed (const TopoDS_Shape& theShape);
//! Computes nodal normals for Poly_Triangulation structure using UV coordinates and surface.
//! Does nothing if triangulation already defines normals.
//! @param theFace [in] the face
//! @param theTris [in] the definition of a face triangulation
static void ComputeNormals (const TopoDS_Face& theFace,
const Handle(Poly_Triangulation)& theTris)
{
Poly_Connect aPolyConnect;
ComputeNormals (theFace, theTris, aPolyConnect);
}
//! Computes nodal normals for Poly_Triangulation structure using UV coordinates and surface.
//! Does nothing if triangulation already defines normals.
//! @param theFace [in] the face
//! @param theTris [in] the definition of a face triangulation
//! @param thePolyConnect [in,out] optional, initialized tool for exploring triangulation
Standard_EXPORT static void ComputeNormals (const TopoDS_Face& theFace,
const Handle(Poly_Triangulation)& theTris,
Poly_Connect& thePolyConnect);
//! Evaluate normals for a triangle of a face.
//! @param[in] theFace the face.
//! @param[in] thePolyConnect the definition of a face triangulation.

View File

@@ -14,8 +14,22 @@
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#include <StepFile_Read.hxx>
// StepFile_Read
// routine assurant l enchainement des operations de lecture d un fichier
// STEP dans un StepModel, en fonction d une cle de reconnaissance
// Retour de la fonction :
// 0 si OK (le StepModel a ete charge)
// -1 si abandon car fichier pas pu etre ouvert
// 1 si erreur en cours de lecture
// Compilation conditionnelle : concerne les mesures de performances
#include <stdio.h>
#include <iostream>
#include <step.tab.hxx>
#include <StepFile_Read.hxx>
#include <StepFile_ReadData.hxx>
#include <Interface_Check.hxx>
@@ -35,13 +49,9 @@
#include <Message.hxx>
#include <Message_Messenger.hxx>
#include <OSD_FileSystem.hxx>
#include <OSD_OpenFile.hxx>
#include <OSD_Timer.hxx>
#include "step.tab.hxx"
#include <stdio.h>
#ifdef OCCT_DEBUG
#define CHRONOMESURE
#endif
@@ -63,15 +73,14 @@ static Standard_Integer StepFile_Read (const char* theName,
const Handle(StepData_FileRecognizer)& theRecogData)
{
// if stream is not provided, open file stream here
std::istream* aStreamPtr = theIStream;
std::shared_ptr<std::istream> aFileStream;
if (aStreamPtr == nullptr)
{
const Handle(OSD_FileSystem)& aFileSystem = OSD_FileSystem::DefaultFileSystem();
aFileStream = aFileSystem->OpenIStream (theName, std::ios::in | std::ios::binary);
aStreamPtr = aFileStream.get();
std::istream *aStreamPtr = theIStream;
std::ifstream aFileStream;
if (!aStreamPtr) {
OSD_OpenStream(aFileStream, theName, std::ios_base::in | std::ios_base::binary);
aStreamPtr = &aFileStream;
}
if (aStreamPtr == nullptr || aStreamPtr->fail())
if (aStreamPtr->fail())
{
return -1;
}

View File

@@ -17,9 +17,6 @@
#ifndef StepFile_Read_HeaderFile
#define StepFile_Read_HeaderFile
#include <Standard_CString.hxx>
#include <Standard_Type.hxx>
#include <iostream>
class StepData_StepModel;

View File

@@ -1,4 +1,3 @@
RWGltf
RWMesh
RWObj
RWPly

View File

@@ -13,3 +13,4 @@ TKGeomAlgo
TKV3d
TKLCAF
TKXCAF
TKRWMesh

View File

@@ -40,7 +40,6 @@
#include <AIS_Shape.hxx>
#include <AIS_DisplayMode.hxx>
#include <AIS_PointCloud.hxx>
#include <BRepLib_PointCloudShape.hxx>
#include <TColStd_MapOfInteger.hxx>
#include <ViewerTest_AutoUpdater.hxx>
#include <ViewerTest_DoubleMapOfInteractiveAndName.hxx>
@@ -6251,12 +6250,6 @@ static Standard_Integer VPointCloud (Draw_Interpretor& theDI,
Standard_Integer theArgNum,
const char** theArgs)
{
if (theArgNum < 2)
{
Message::SendFail ("Syntax error: wrong number of arguments");
return 1;
}
Handle(AIS_InteractiveContext) anAISContext = ViewerTest::GetAISContext();
if (anAISContext.IsNull())
{
@@ -6264,114 +6257,83 @@ static Standard_Integer VPointCloud (Draw_Interpretor& theDI,
return 1;
}
TCollection_AsciiString aName;
TopoDS_Shape aShape;
// command to execute
enum Command
{
CloudForShape, // generate point cloud for shape
CloudSphere, // generate point cloud for generic sphere
Unknow
};
TCollection_AsciiString aDistribution;
gp_Pnt aDistCenter;
Standard_Real aDistRadius = 0.0;
Standard_Integer aDistNbPoints = 0;
// parse options
bool toRandColors = false;
bool hasNormals = true, hasUV = false;
bool isDensityPoints = false;
Standard_Real aDensity = 0.0, aDist = 0.0;
Standard_Real aTol = Precision::Confusion();
// count number of non-optional command arguments
Command aCmd = Unknow;
Standard_Integer aCmdArgs = 0;
for (Standard_Integer anArgIter = 1; anArgIter < theArgNum; ++anArgIter)
{
TCollection_AsciiString aFlag (theArgs[anArgIter]);
Standard_CString anArg = theArgs[anArgIter];
TCollection_AsciiString aFlag (anArg);
aFlag.LowerCase();
if (aFlag.IsRealValue (Standard_True) || aFlag.Search ("-") != 1)
{
aCmdArgs++;
}
}
switch (aCmdArgs)
{
case 2 : aCmd = CloudForShape; break;
case 7 : aCmd = CloudSphere; break;
default :
Message::SendFail ("Syntax error: wrong number of arguments! See usage:");
theDI.PrintHelp (theArgs[0]);
return 1;
}
// parse options
Standard_Boolean toRandColors = Standard_False;
Standard_Boolean hasNormals = Standard_True;
Standard_Boolean isSetArgNorm = Standard_False;
Standard_Boolean hasUV = Standard_False;
for (Standard_Integer anArgIter = 1; anArgIter < theArgNum; ++anArgIter)
{
Standard_CString anArg = theArgs[anArgIter];
TCollection_AsciiString aFlag (anArg);
aFlag.LowerCase();
if (aFlag == "-randcolors"
|| aFlag == "-randcolor")
{
toRandColors = Draw::ParseOnOffIterator (theArgNum, theArgs, anArgIter);
if (isSetArgNorm && hasNormals)
{
Message::SendFail ("Syntax error: normals can not be enabled with colors at the same time");
return 1;
}
toRandColors = Standard_True;
hasNormals = Standard_False;
}
else if (aFlag == "-normals"
|| aFlag == "-normal")
{
hasNormals = Draw::ParseOnOffIterator (theArgNum, theArgs, anArgIter);
if (toRandColors)
{
Message::SendFail ("Syntax error: normals can not be enabled with colors at the same time");
return 1;
}
isSetArgNorm = Standard_True;
hasNormals = Standard_True;
}
else if (aFlag == "-nonormals"
|| aFlag == "-nonormal")
{
hasNormals = !Draw::ParseOnOffIterator (theArgNum, theArgs, anArgIter);
isSetArgNorm = Standard_True;
hasNormals = Standard_False;
}
else if (aFlag == "-uv"
|| aFlag == "-texels")
{
hasUV = Draw::ParseOnOffIterator (theArgNum, theArgs, anArgIter);
}
else if ((aFlag == "-dist"
|| aFlag == "-distance")
&& anArgIter + 1 < theArgNum
&& Draw::ParseReal (theArgs[anArgIter + 1], aDist))
{
++anArgIter;
if (aDist < 0.0)
{
theDI << "Syntax error: -distance value should be >= 0.0";
return 1;
}
aDist = Max (aDist, Precision::Confusion());
}
else if ((aFlag == "-dens"
|| aFlag == "-density")
&& anArgIter + 1 < theArgNum
&& Draw::ParseReal (theArgs[anArgIter + 1], aDensity))
{
++anArgIter;
isDensityPoints = Standard_True;
if (aDensity <= 0.0)
{
theDI << "Syntax error: -density value should be > 0.0";
return 1;
}
}
else if ((aFlag == "-tol"
|| aFlag == "-tolerance")
&& anArgIter + 1 < theArgNum
&& Draw::ParseReal (theArgs[anArgIter + 1], aTol))
{
++anArgIter;
if (aTol < Precision::Confusion())
{
theDI << "Syntax error: -tol value should be >= " << Precision::Confusion();
return 1;
}
}
else if ((aFlag == "-surface"
|| aFlag == "-volume")
&& anArgIter + 5 < theArgNum)
{
aDistribution = aFlag;
aDistCenter.SetCoord (Draw::Atof (theArgs[anArgIter + 1]),
Draw::Atof (theArgs[anArgIter + 2]),
Draw::Atof (theArgs[anArgIter + 3]));
aDistRadius = Draw::Atof (theArgs[anArgIter + 4]);
aDistNbPoints = Draw::Atoi (theArgs[anArgIter + 5]);
anArgIter += 5;
}
else if (aName.IsEmpty())
{
aName = theArgs[anArgIter];
}
else if (aShape.IsNull())
{
aShape = DBRep::Get (theArgs[anArgIter]);
if (aShape.IsNull())
{
theDI << "Syntax error: invalid shape '" << theArgs[anArgIter] << "'";
return 1;
}
}
else
{
theDI << "Syntax error at '" << theArgs[anArgIter] << "'";
return 1;
hasUV = Standard_True;
}
}
Standard_CString aName = theArgs[1];
Graphic3d_ArrayFlags aFlags = Graphic3d_ArrayFlags_None;
if (hasNormals)
{
@@ -6388,80 +6350,125 @@ static Standard_Integer VPointCloud (Draw_Interpretor& theDI,
// generate arbitrary set of points
Handle(Graphic3d_ArrayOfPoints) anArrayPoints;
if (!aShape.IsNull())
if (aCmd == CloudForShape)
{
class PointCloudPntFiller : public BRepLib_PointCloudShape
Standard_CString aShapeName = theArgs[2];
TopoDS_Shape aShape = DBRep::Get (aShapeName);
if (aShape.IsNull())
{
public:
PointCloudPntFiller (Standard_Real theTol) : BRepLib_PointCloudShape (TopoDS_Shape(), theTol) {}
void SetPointArray (const Handle(Graphic3d_ArrayOfPoints)& thePoints) { myPoints = thePoints; }
protected:
virtual void addPoint (const gp_Pnt& thePoint,
const gp_Vec& theNorm,
const gp_Pnt2d& theUV,
const TopoDS_Shape& ) Standard_OVERRIDE
{
const Standard_Integer aPntIndex = myPoints->AddVertex (thePoint, theUV);
if (theNorm.SquareMagnitude() > gp::Resolution())
{
myPoints->SetVertexNormal (aPntIndex, theNorm);
}
if (myPoints->HasVertexColors())
{
Quantity_Color aColor (360.0 * Standard_Real(aPntIndex) / Standard_Real(myPoints->VertexNumberAllocated()),
1.0, 0.5, Quantity_TOC_HLS);
myPoints->SetVertexColor (aPntIndex, aColor);
}
}
private:
Handle(Graphic3d_ArrayOfPoints) myPoints;
};
PointCloudPntFiller aPoitCloudTool (aTol);
aPoitCloudTool.SetShape (aShape);
aPoitCloudTool.SetDistance (aDist);
Standard_Integer aNbPoints = isDensityPoints
? aPoitCloudTool.NbPointsByDensity (aDensity)
: aPoitCloudTool.NbPointsByTriangulation();
theDI << "Number of the generated points : " << aNbPoints << "\n";
anArrayPoints = new Graphic3d_ArrayOfPoints (aNbPoints, aFlags);
aPoitCloudTool.SetPointArray (anArrayPoints);
Standard_Boolean isDone = isDensityPoints
? aPoitCloudTool.GeneratePointsByDensity (aDensity)
: aPoitCloudTool.GeneratePointsByTriangulation();
if (!isDone)
{
Message::SendFail() << "Error: Point cloud was not generated";
Message::SendFail() << "Error: no shape with name '" << aShapeName << "' found";
return 1;
}
}
else if (!aDistribution.IsEmpty())
{
const bool isSurface = aDistribution == "-surface";
anArrayPoints = new Graphic3d_ArrayOfPoints (aDistNbPoints, aFlags);
std::mt19937 aRandomGenerator(0);
std::uniform_real_distribution<> anAlphaDistrib(0.0, 2.0 * M_PI);
std::uniform_real_distribution<> aBetaDistrib (0.0, 2.0 * M_PI);
std::uniform_real_distribution<> aRadiusDistrib(0.0, aDistRadius);
for (Standard_Integer aPntIt = 0; aPntIt < aDistNbPoints; ++aPntIt)
// calculate number of points
TopLoc_Location aLocation;
Standard_Integer aNbPoints = 0;
for (TopExp_Explorer aFaceIt (aShape, TopAbs_FACE); aFaceIt.More(); aFaceIt.Next())
{
Standard_Real anAlpha = anAlphaDistrib(aRandomGenerator);
Standard_Real aBeta = aBetaDistrib (aRandomGenerator);
Standard_Real aDistance = isSurface ? aDistRadius : aRadiusDistrib (aRandomGenerator);
const TopoDS_Face& aFace = TopoDS::Face (aFaceIt.Current());
Handle(Poly_Triangulation) aTriangulation = BRep_Tool::Triangulation (aFace, aLocation);
if (!aTriangulation.IsNull())
{
aNbPoints += aTriangulation->NbNodes();
}
}
if (aNbPoints < 3)
{
Message::SendFail ("Error: shape should be triangulated");
return 1;
}
anArrayPoints = new Graphic3d_ArrayOfPoints (aNbPoints, aFlags);
for (TopExp_Explorer aFaceIt (aShape, TopAbs_FACE); aFaceIt.More(); aFaceIt.Next())
{
const TopoDS_Face& aFace = TopoDS::Face (aFaceIt.Current());
Handle(Poly_Triangulation) aTriangulation = BRep_Tool::Triangulation (aFace, aLocation);
if (aTriangulation.IsNull())
{
continue;
}
const gp_Trsf& aTrsf = aLocation.Transformation();
// extract normals from nodes
TColgp_Array1OfDir aNormals (1, hasNormals ? aTriangulation->NbNodes() : 1);
if (hasNormals)
{
Poly_Connect aPolyConnect (aTriangulation);
StdPrs_ToolTriangulatedShape::Normal (aFace, aPolyConnect, aNormals);
}
for (Standard_Integer aNodeIter = 1; aNodeIter <= aTriangulation->NbNodes(); ++aNodeIter)
{
gp_Pnt aPoint = aTriangulation->Node (aNodeIter);
if (!aLocation.IsIdentity())
{
aPoint.Transform (aTrsf);
if (hasNormals)
{
aNormals (aNodeIter).Transform (aTrsf);
}
}
// add vertex into array of points
const Standard_Integer anIndexOfPoint = anArrayPoints->AddVertex (aPoint);
if (toRandColors)
{
Quantity_Color aColor (360.0 * Standard_Real(anIndexOfPoint) / Standard_Real(aNbPoints),
1.0, 0.5, Quantity_TOC_HLS);
anArrayPoints->SetVertexColor (anIndexOfPoint, aColor);
}
if (hasNormals)
{
anArrayPoints->SetVertexNormal (anIndexOfPoint, aNormals (aNodeIter));
}
if (hasUV
&& aTriangulation->HasUVNodes())
{
anArrayPoints->SetVertexTexel (anIndexOfPoint, aTriangulation->UVNode (aNodeIter));
}
}
}
}
else if (aCmd == CloudSphere)
{
Standard_Real aCenterX = Draw::Atof (theArgs[2]);
Standard_Real aCenterY = Draw::Atof (theArgs[3]);
Standard_Real aCenterZ = Draw::Atof (theArgs[4]);
Standard_Real aRadius = Draw::Atof (theArgs[5]);
Standard_Integer aNbPoints = Draw::Atoi (theArgs[6]);
TCollection_AsciiString aDistribution = TCollection_AsciiString(theArgs[7]);
aDistribution.LowerCase();
if ( aDistribution != "surface" && aDistribution != "volume" )
{
Message::SendFail ("Syntax error: wrong arguments. See usage:");
theDI.PrintHelp (theArgs[0]);
return 1;
}
Standard_Boolean isSurface = aDistribution == "surface";
gp_Pnt aCenter(aCenterX, aCenterY, aCenterZ);
anArrayPoints = new Graphic3d_ArrayOfPoints (aNbPoints, aFlags);
for (Standard_Integer aPntIt = 0; aPntIt < aNbPoints; ++aPntIt)
{
Standard_Real anAlpha = (Standard_Real (rand() % 2000) / 1000.0) * M_PI;
Standard_Real aBeta = (Standard_Real (rand() % 2000) / 1000.0) * M_PI;
Standard_Real aDistance = isSurface ?
aRadius : (Standard_Real (rand() % aNbPoints) / aNbPoints) * aRadius;
gp_Dir aDir (Cos (anAlpha) * Sin (aBeta),
Sin (anAlpha),
Cos (anAlpha) * Cos (aBeta));
gp_Pnt aPoint = aDistCenter.Translated (aDir.XYZ() * aDistance);
gp_Pnt aPoint = aCenter.Translated (aDir.XYZ() * aDistance);
const Standard_Integer anIndexOfPoint = anArrayPoints->AddVertex (aPoint);
if (toRandColors)
{
Quantity_Color aColor (360.0 * Standard_Real (anIndexOfPoint) / Standard_Real (aDistNbPoints),
Quantity_Color aColor (360.0 * Standard_Real (anIndexOfPoint) / Standard_Real (aNbPoints),
1.0, 0.5, Quantity_TOC_HLS);
anArrayPoints->SetVertexColor (anIndexOfPoint, aColor);
}
@@ -6477,16 +6484,11 @@ static Standard_Integer VPointCloud (Draw_Interpretor& theDI,
}
}
}
else
{
Message::SendFail ("Error: wrong number of arguments");
return 1;
}
// set array of points in point cloud object
Handle(AIS_PointCloud) aPointCloud = new AIS_PointCloud();
aPointCloud->SetPoints (anArrayPoints);
ViewerTest::Display (aName, aPointCloud);
VDisplayAISObject (aName, aPointCloud);
return 0;
}
@@ -7147,23 +7149,18 @@ Prints the default vertex draw mode without -set parameter.
)" /* [vvertexmode] */);
addCmd ("vpointcloud", VPointCloud, /* [vpointcloud] */ R"(
vpointcloud name shape [-randColor {0|1}]=0 [-normals {0|1}]=1 [-uv {0|1}]=0
[-distance Value]=0.0 [-density Value] [-tolerance Value]
vpointcloud name shape [-randColor] [-normals] [-noNormals] [-uv]
Create an interactive object for arbitrary set of points from triangulated shape.
vpointcloud name {-surface|-volume} x y z r npts
[-randColor] [-normals] [-uv]
vpointcloud name x y z r npts {surface|volume}
... [-randColor] [-normals] [-noNormals] [-uv]
Create arbitrary set of points (npts) randomly distributed
on spheric surface or within spheric volume (x y z r).
Additional options:
-normals generate or not normal per point
-uv generate UV (texel) coordinates per point
-randColor generate random color per point
-distance distance from shape into the range [0, Value];
-density density of points to generate randomly on surface;
-tolerance cloud generator's tolerance; default value is Precision::Confusion();
-randColor - generate random color per point
-normals - generate normal per point (default)
-noNormals - do not generate normal per point
)" /* [vpointcloud] */);
addCmd ("vpriority", VPriority, /* [vpriority] */ R"(

View File

@@ -14,15 +14,21 @@
// commercial license or contractual agreement.
#include <VrmlData_ShapeConvert.hxx>
#include <VrmlData_Scene.hxx>
#include <VrmlData_Group.hxx>
#include <VrmlData_Appearance.hxx>
#include <VrmlData_Coordinate.hxx>
#include <VrmlData_Group.hxx>
#include <VrmlData_IndexedFaceSet.hxx>
#include <VrmlData_IndexedLineSet.hxx>
#include <VrmlData_Scene.hxx>
#include <VrmlData_ShapeNode.hxx>
#include <BRep_Builder.hxx>
#include <BRep_Tool.hxx>
#include <BRepAdaptor_Curve.hxx>
#include <Geom_Surface.hxx>
#include <GeomLib.hxx>
#include <GCPnts_TangentialDeflection.hxx>
#include <NCollection_DataMap.hxx>
#include <Poly_Triangulation.hxx>
#include <Poly_Connect.hxx>
@@ -33,7 +39,6 @@
#include <TColgp_Array1OfPnt2d.hxx>
#include <TDataStd_Name.hxx>
#include <TDF_Label.hxx>
//#include <TDF_LabelSequence.hxx>
#include <TDocStd_Document.hxx>
#include <TopExp_Explorer.hxx>
#include <TopoDS.hxx>
@@ -41,14 +46,11 @@
#include <TopoDS_Face.hxx>
#include <TopoDS_Shape.hxx>
#include <TopoDS_Wire.hxx>
#include <GCPnts_TangentialDeflection.hxx>
#include <BRepAdaptor_Curve.hxx>
#include <TColStd_Array1OfReal.hxx>
#include <TColStd_HArray1OfReal.hxx>
#include <TShort_Array1OfShortReal.hxx>
#include <GeomLib.hxx>
#include <TShort_HArray1OfShortReal.hxx>
#include <VrmlData_Appearance.hxx>
#include <RWMesh_FaceIterator.hxx>
#include <XCAFDoc_ColorTool.hxx>
#include <XCAFDoc_DocumentTool.hxx>
#include <XCAFDoc_ShapeTool.hxx>
@@ -575,7 +577,6 @@ Handle(VrmlData_Appearance) VrmlData_ShapeConvert::defaultMaterialEdge () const
return anAppearance;
}
//=======================================================================
//function : addShape
//purpose : Adds the shape from the document
@@ -584,33 +585,18 @@ void VrmlData_ShapeConvert::addShape (const Handle(VrmlData_Group)& theParent,
const TDF_Label& theLabel,
const Handle(TDocStd_Document)& theDoc)
{
Handle(XCAFDoc_ShapeTool) aShapeTool = XCAFDoc_DocumentTool::ShapeTool(theDoc->Main());
const TopoDS_Shape aShape = XCAFDoc_ShapeTool::GetShape(theLabel);
Handle(XCAFDoc_ColorTool) aColorTool = XCAFDoc_DocumentTool::ColorTool(theDoc->Main());
Handle(XCAFDoc_VisMaterialTool) aMatTool = XCAFDoc_DocumentTool::VisMaterialTool(theDoc->Main());
NCollection_DataMap<TopoDS_Shape, TDF_Label> aChildShapeToLabels;
TDF_LabelSequence aChildLabels;
aShapeTool->GetSubShapes(theLabel, aChildLabels);
for (TDF_LabelSequence::Iterator aChildIter(aChildLabels); aChildIter.More(); aChildIter.Next())
Handle(VrmlData_Group) aGroup;
Standard_Integer aNbFaces = 0;
for (RWMesh_FaceIterator aFaceIter (theLabel, TopLoc_Location(), true); aFaceIter.More(); aFaceIter.Next())
{
const TDF_Label& aChildLabel = aChildIter.Value();
TopoDS_Shape aChildShape;
if (aShapeTool->GetShape(aChildLabel, aChildShape))
{
aChildShapeToLabels.Bind(aChildShape, aChildLabel);
}
++aNbFaces;
}
const TopoDS_Shape aShape = aShapeTool->GetShape(theLabel);
Handle(VrmlData_Group) aGroup = 0L;
TopExp_Explorer anExp(aShape, TopAbs_FACE);
Standard_Integer nbFaces = 0;
for (; anExp.More(); anExp.Next()) {
nbFaces++;
}
Handle(TDataStd_Name) aNameAttribute;
theLabel.FindAttribute(TDataStd_Name::GetID(), aNameAttribute);
if (nbFaces > 1)
if (aNbFaces > 1)
{
if (!aNameAttribute.IsNull())
{
@@ -630,112 +616,88 @@ void VrmlData_ShapeConvert::addShape (const Handle(VrmlData_Group)& theParent,
}
}
anExp.Init(aShape, TopAbs_FACE);
for (; anExp.More(); anExp.Next()) {
for (RWMesh_FaceIterator aFaceIter (theLabel, TopLoc_Location(), true); aFaceIter.More(); aFaceIter.Next())
{
TopLoc_Location aLoc;
Handle(VrmlData_Geometry) aTShapeNode =
makeTShapeNode(anExp.Current(), TopAbs_FACE, aLoc);
if (!aTShapeNode.IsNull())
const TopoDS_Face& aFace = aFaceIter.Face();
Handle(VrmlData_Geometry) aTShapeNode = makeTShapeNode (aFace, TopAbs_FACE, aLoc);
if (aTShapeNode.IsNull())
{
Handle(VrmlData_ShapeNode) aShapeNode = 0L;
if (aGroup.IsNull() && !aNameAttribute.IsNull())
{
TCollection_AsciiString aName = aNameAttribute->Get();
aName.ChangeAll(' ', '_');
aName.ChangeAll('#', '_');
aShapeNode = new VrmlData_ShapeNode(myScene, aName.ToCString());
}
else
{
aShapeNode = new VrmlData_ShapeNode(myScene, 0L);
}
continue;
}
// set color
XCAFPrs_Style aStyle;
Quantity_ColorRGBA aColor;
TDF_Label aLabel, anAttribLab;
if (aChildShapeToLabels.Find (anExp.Current(), aLabel))
{
Handle(XCAFDoc_VisMaterial) aVisMat = aMatTool->GetShapeMaterial (aLabel);
if (!aVisMat.IsNull()
&& !aVisMat->IsEmpty())
{
anAttribLab = aVisMat->Label();
aStyle.SetMaterial (aVisMat);
}
else if (aColorTool->GetColor (aLabel, XCAFDoc_ColorSurf, anAttribLab)
|| aColorTool->GetColor (aLabel, XCAFDoc_ColorGen, anAttribLab))
{
aColorTool->GetColor (anAttribLab, aColor);
aStyle.SetColorSurf (aColor);
}
}
if (!aStyle.IsSetColorSurf()
&& aStyle.Material().IsNull())
{
Handle(XCAFDoc_VisMaterial) aVisMat = aMatTool->GetShapeMaterial (theLabel);
if (!aVisMat.IsNull()
&& !aVisMat->IsEmpty())
{
anAttribLab = aVisMat->Label();
aStyle.SetMaterial (aVisMat);
}
if (aColorTool->GetColor (theLabel, XCAFDoc_ColorSurf, anAttribLab)
|| aColorTool->GetColor (theLabel, XCAFDoc_ColorGen, anAttribLab))
{
aColorTool->GetColor (anAttribLab, aColor);
aStyle.SetColorSurf (aColor);
}
}
if (!aStyle.IsSetColorSurf()
&& aStyle.Material().IsNull())
{
aShapeNode->SetAppearance(defaultMaterialFace());
}
else
{
aShapeNode->SetAppearance (makeMaterialFromStyle (aStyle, anAttribLab));
}
Handle(VrmlData_ShapeNode) aShapeNode = 0L;
if (aGroup.IsNull() && !aNameAttribute.IsNull())
{
TCollection_AsciiString aName = aNameAttribute->Get();
aName.ChangeAll(' ', '_');
aName.ChangeAll('#', '_');
aShapeNode = new VrmlData_ShapeNode(myScene, aName.ToCString());
}
else
{
aShapeNode = new VrmlData_ShapeNode(myScene, 0L);
}
myScene.AddNode(aShapeNode, theParent.IsNull() && aGroup.IsNull());
aShapeNode->SetGeometry(aTShapeNode);
if (aLoc.IsIdentity())
// set color
const XCAFPrs_Style& aStyle = aFaceIter.FaceStyle();
TDF_Label anAttribLab;
if (!aStyle.Material().IsNull()
&& !aStyle.Material()->IsEmpty())
{
anAttribLab = aStyle.Material()->Label();
}
else if (aStyle.IsSetColorSurf())
{
aColorTool->FindColor (aStyle.GetColorSurfRGBA(), anAttribLab);
}
if (!aStyle.IsSetColorSurf()
&& aStyle.Material().IsNull())
{
aShapeNode->SetAppearance (defaultMaterialFace());
}
else
{
aShapeNode->SetAppearance (makeMaterialFromStyle (aStyle, anAttribLab));
}
myScene.AddNode(aShapeNode, theParent.IsNull() && aGroup.IsNull());
aShapeNode->SetGeometry(aTShapeNode);
if (aLoc.IsIdentity())
{
// Store the shape node directly into the main Group.
if (!aGroup.IsNull())
{
// Store the shape node directly into the main Group.
if (!aGroup.IsNull())
{
aGroup->AddNode(aShapeNode);
}
else if (!theParent.IsNull())
{
theParent->AddNode(aShapeNode);
}
aGroup->AddNode(aShapeNode);
}
else
else if (!theParent.IsNull())
{
// Create a Transform grouping node
Handle(VrmlData_Group) aTrans = new VrmlData_Group(myScene, 0L,
Standard_True);
gp_Trsf aTrsf(aLoc);
if (fabs(myScale - 1.) > Precision::Confusion())
{
const gp_XYZ aTransl = aTrsf.TranslationPart() * myScale;
aTrsf.SetTranslationPart(aTransl);
}
aTrans->SetTransform(aTrsf);
myScene.AddNode(aTrans, theParent.IsNull() && aGroup.IsNull());
if (!aGroup.IsNull())
{
aGroup->AddNode(aTrans);
}
else if (!theParent.IsNull())
{
theParent->AddNode(aTrans);
}
// Store the shape node under the transform.
aTrans->AddNode(aShapeNode);
theParent->AddNode(aShapeNode);
}
}
else
{
// Create a Transform grouping node
Handle(VrmlData_Group) aTrans = new VrmlData_Group (myScene, 0L, Standard_True);
gp_Trsf aTrsf(aLoc);
if (fabs(myScale - 1.) > Precision::Confusion())
{
const gp_XYZ aTransl = aTrsf.TranslationPart() * myScale;
aTrsf.SetTranslationPart(aTransl);
}
aTrans->SetTransform(aTrsf);
myScene.AddNode(aTrans, theParent.IsNull() && aGroup.IsNull());
if (!aGroup.IsNull())
{
aGroup->AddNode(aTrans);
}
else if (!theParent.IsNull())
{
theParent->AddNode(aTrans);
}
// Store the shape node under the transform.
aTrans->AddNode(aShapeNode);
}
}
}

View File

@@ -19,7 +19,6 @@
#include <Aspect_TypeOfMarker.hxx>
#include <Bnd_Box.hxx>
#include <BRep_Builder.hxx>
#include <BRepLib_PointCloudShape.hxx>
#include <DBRep.hxx>
#include <DDocStd.hxx>
#include <DDocStd_DrawDocument.hxx>
@@ -46,13 +45,10 @@
#include <Quantity_NameOfColor.hxx>
#include <RWGltf_CafReader.hxx>
#include <RWGltf_CafWriter.hxx>
#include <RWMesh_FaceIterator.hxx>
#include <RWStl.hxx>
#include <RWObj.hxx>
#include <RWObj_CafReader.hxx>
#include <RWObj_CafWriter.hxx>
#include <RWPly_CafWriter.hxx>
#include <RWPly_PlyWriterContext.hxx>
#include <SelectMgr_SelectionManager.hxx>
#include <Standard_ErrorHandler.hxx>
#include <StdSelect_ViewerSelector3d.hxx>
@@ -66,7 +62,6 @@
#include <TDataStd_Name.hxx>
#include <TDocStd_Application.hxx>
#include <TDocStd_Document.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Face.hxx>
#include <TopoDS_Shape.hxx>
#include <UnitsAPI.hxx>
@@ -80,7 +75,6 @@
#include <VrmlData_ShapeConvert.hxx>
#include <XCAFDoc_DocumentTool.hxx>
#include <XCAFDoc_ShapeTool.hxx>
#include <XCAFPrs_DocumentExplorer.hxx>
#include <XSAlgo.hxx>
#include <XSAlgo_AlgoContainer.hxx>
#include <XSDRAW.hxx>
@@ -2061,275 +2055,6 @@ static Standard_Integer meshinfo(Draw_Interpretor& di,
return 0;
}
//=======================================================================
//function : writeply
//purpose : write PLY file
//=======================================================================
static Standard_Integer WritePly (Draw_Interpretor& theDI,
Standard_Integer theNbArgs,
const char** theArgVec)
{
Handle(TDocStd_Document) aDoc;
Handle(TDocStd_Application) anApp = DDocStd::GetApplication();
TCollection_AsciiString aShapeName, aFileName;
Standard_Real aDist = 0.0;
Standard_Real aDens = Precision::Infinite();
Standard_Real aTol = Precision::Confusion();
bool hasColors = true, hasNormals = true, hasTexCoords = false, hasPartId = true, hasFaceId = false;
bool isPntSet = false, isDensityPoints = false;
TColStd_IndexedDataMapOfStringString aFileInfo;
for (Standard_Integer anArgIter = 1; anArgIter < theNbArgs; ++anArgIter)
{
TCollection_AsciiString anArg (theArgVec[anArgIter]);
anArg.LowerCase();
if (anArg == "-normal")
{
hasNormals = Draw::ParseOnOffIterator (theNbArgs, theArgVec, anArgIter);
}
else if (anArg == "-nonormal")
{
hasNormals = !Draw::ParseOnOffIterator (theNbArgs, theArgVec, anArgIter);
}
else if (anArg == "-color"
|| anArg == "-nocolor"
|| anArg == "-colors"
|| anArg == "-nocolors")
{
hasColors = Draw::ParseOnOffNoIterator (theNbArgs, theArgVec, anArgIter);
}
else if (anArg == "-uv"
|| anArg == "-nouv")
{
hasTexCoords = Draw::ParseOnOffNoIterator (theNbArgs, theArgVec, anArgIter);
}
else if (anArg == "-partid")
{
hasPartId = Draw::ParseOnOffNoIterator (theNbArgs, theArgVec, anArgIter);
hasFaceId = hasFaceId && !hasPartId;
}
else if (anArg == "-surfid"
|| anArg == "-surfaceid"
|| anArg == "-faceid")
{
hasFaceId = Draw::ParseOnOffNoIterator (theNbArgs, theArgVec, anArgIter);
hasPartId = hasPartId && !hasFaceId;
}
else if (anArg == "-pntset"
|| anArg == "-pntcloud"
|| anArg == "-pointset"
|| anArg == "-pointcloud"
|| anArg == "-cloud"
|| anArg == "-points")
{
isPntSet = Draw::ParseOnOffIterator (theNbArgs, theArgVec, anArgIter);
}
else if ((anArg == "-dist"
|| anArg == "-distance")
&& anArgIter + 1 < theNbArgs
&& Draw::ParseReal (theArgVec[anArgIter + 1], aDist))
{
++anArgIter;
isPntSet = true;
if (aDist < 0.0)
{
theDI << "Syntax error: -distance value should be >= 0.0";
return 1;
}
aDist = Max (aDist, Precision::Confusion());
}
else if ((anArg == "-dens"
|| anArg == "-density")
&& anArgIter + 1 < theNbArgs
&& Draw::ParseReal (theArgVec[anArgIter + 1], aDens))
{
++anArgIter;
isDensityPoints = Standard_True;
isPntSet = true;
if (aDens <= 0.0)
{
theDI << "Syntax error: -density value should be > 0.0";
return 1;
}
}
else if ((anArg == "-tol"
|| anArg == "-tolerance")
&& anArgIter + 1 < theNbArgs
&& Draw::ParseReal (theArgVec[anArgIter + 1], aTol))
{
++anArgIter;
isPntSet = true;
if (aTol < Precision::Confusion())
{
theDI << "Syntax error: -tol value should be >= " << Precision::Confusion();
return 1;
}
}
else if (anArg == "-comments"
&& anArgIter + 1 < theNbArgs)
{
aFileInfo.Add ("Comments", theArgVec[++anArgIter]);
}
else if (anArg == "-author"
&& anArgIter + 1 < theNbArgs)
{
aFileInfo.Add ("Author", theArgVec[++anArgIter]);
}
else if (aDoc.IsNull())
{
if (aShapeName.IsEmpty())
{
aShapeName = theArgVec[anArgIter];
}
Standard_CString aNameVar = theArgVec[anArgIter];
DDocStd::GetDocument (aNameVar, aDoc, false);
if (aDoc.IsNull())
{
TopoDS_Shape aShape = DBRep::Get (aNameVar);
if (!aShape.IsNull())
{
anApp->NewDocument (TCollection_ExtendedString ("BinXCAF"), aDoc);
Handle(XCAFDoc_ShapeTool) aShapeTool = XCAFDoc_DocumentTool::ShapeTool (aDoc->Main());
aShapeTool->AddShape (aShape);
}
}
}
else if (aFileName.IsEmpty())
{
aFileName = theArgVec[anArgIter];
}
else
{
theDI << "Syntax error at '" << theArgVec[anArgIter] << "'";
return 1;
}
}
if (aDoc.IsNull()
&& !aShapeName.IsEmpty())
{
theDI << "Syntax error: '" << aShapeName << "' is not a shape nor document";
return 1;
}
else if (aDoc.IsNull()
|| aFileName.IsEmpty())
{
theDI << "Syntax error: wrong number of arguments";
return 1;
}
TDF_LabelSequence aRootLabels;
Handle(XCAFDoc_ShapeTool) aShapeTool = XCAFDoc_DocumentTool::ShapeTool (aDoc->Main());
aShapeTool->GetFreeShapes (aRootLabels);
if (aRootLabels.IsEmpty())
{
theDI << "Error: empty document";
return 1;
}
if (isPntSet)
{
class PointCloudPlyWriter : public BRepLib_PointCloudShape, public RWPly_PlyWriterContext
{
public:
PointCloudPlyWriter (Standard_Real theTol)
: BRepLib_PointCloudShape (TopoDS_Shape(), theTol) {}
void AddFaceColor (const TopoDS_Shape& theFace, const Graphic3d_Vec4ub& theColor)
{ myFaceColor.Bind (theFace, theColor); }
protected:
virtual void addPoint (const gp_Pnt& thePoint,
const gp_Vec& theNorm,
const gp_Pnt2d& theUV,
const TopoDS_Shape& theFace)
{
Graphic3d_Vec4ub aColor;
myFaceColor.Find (theFace, aColor);
RWPly_PlyWriterContext::WriteVertex (thePoint,
Graphic3d_Vec3 ((float )theNorm.X(), (float )theNorm.Y(), (float )theNorm.Z()),
Graphic3d_Vec2 ((float )theUV.X(), (float )theUV.Y()),
aColor);
}
private:
NCollection_DataMap<TopoDS_Shape, Graphic3d_Vec4ub> myFaceColor;
};
PointCloudPlyWriter aPlyCtx (aTol);
aPlyCtx.SetNormals (hasNormals);
aPlyCtx.SetColors (hasColors);
aPlyCtx.SetTexCoords (hasTexCoords);
TopoDS_Compound aComp;
BRep_Builder().MakeCompound (aComp);
for (XCAFPrs_DocumentExplorer aDocExplorer (aDoc, aRootLabels, XCAFPrs_DocumentExplorerFlags_OnlyLeafNodes);
aDocExplorer.More(); aDocExplorer.Next())
{
const XCAFPrs_DocumentNode& aDocNode = aDocExplorer.Current();
for (RWMesh_FaceIterator aFaceIter (aDocNode.RefLabel, aDocNode.Location, true, aDocNode.Style); aFaceIter.More(); aFaceIter.Next())
{
BRep_Builder().Add (aComp, aFaceIter.Face());
Graphic3d_Vec4ub aColorVec (255);
if (aFaceIter.HasFaceColor())
{
Graphic3d_Vec4 aColorF = aFaceIter.FaceColor();
aColorVec.SetValues ((unsigned char )int(aColorF.r() * 255.0f),
(unsigned char )int(aColorF.g() * 255.0f),
(unsigned char )int(aColorF.b() * 255.0f),
(unsigned char )int(aColorF.a() * 255.0f));
}
aPlyCtx.AddFaceColor (aFaceIter.Face(), aColorVec);
}
}
aPlyCtx.SetShape (aComp);
Standard_Integer aNbPoints = isDensityPoints
? aPlyCtx.NbPointsByDensity (aDens)
: aPlyCtx.NbPointsByTriangulation();
if (aNbPoints <= 0)
{
theDI << "Error: unable to generate points";
return 0;
}
if (!aPlyCtx.Open (aFileName)
|| !aPlyCtx.WriteHeader (aNbPoints, 0, TColStd_IndexedDataMapOfStringString()))
{
theDI << "Error: unable to create file '" << aFileName << "'";
return 0;
}
Standard_Boolean isDone = isDensityPoints
? aPlyCtx.GeneratePointsByDensity (aDens)
: aPlyCtx.GeneratePointsByTriangulation();
if (!isDone)
{
theDI << "Error: Point cloud was not generated in file '" << aFileName << "'";
}
else if (!aPlyCtx.Close())
{
theDI << "Error: Point cloud file '" << aFileName << "' was not written";
}
else
{
theDI << aNbPoints;
}
}
else
{
Handle(Draw_ProgressIndicator) aProgress = new Draw_ProgressIndicator (theDI, 1);
RWPly_CafWriter aPlyCtx (aFileName);
aPlyCtx.SetNormals (hasNormals);
aPlyCtx.SetColors (hasColors);
aPlyCtx.SetTexCoords (hasTexCoords);
aPlyCtx.SetPartId (hasPartId);
aPlyCtx.SetFaceId (hasFaceId);
aPlyCtx.Perform (aDoc, aFileInfo, aProgress->Start());
}
return 0;
}
//-----------------------------------------------------------------------------
void XSDRAWSTLVRML::InitCommands (Draw_Interpretor& theCommands)
@@ -2435,25 +2160,6 @@ void XSDRAWSTLVRML::InitCommands (Draw_Interpretor& theCommands)
theCommands.Add ("meshdeform", "display deformed mesh", __FILE__, meshdeform, g );
theCommands.Add ("mesh_edge_width", "set width of edges", __FILE__, mesh_edge_width, g );
theCommands.Add ("meshinfo", "displays the number of nodes and triangles", __FILE__, meshinfo, g );
theCommands.Add ("WritePly", R"(
WritePly Doc file [-normals {0|1}]=1 [-colors {0|1}]=1 [-uv {0|1}]=0 [-partId {0|1}]=1 [-faceId {0|1}]=0
[-pointCloud {0|1}]=0 [-distance Value]=0.0 [-density Value] [-tolerance Value]
Write document or triangulated shape into PLY file.
-normals write per-vertex normals
-colors write per-vertex colors
-uv write per-vertex UV coordinates
-partId write per-element part index (alternative to -faceId)
-faceId write per-element face index (alternative to -partId)
Generate point cloud out of the shape and write it into PLY file.
-pointCloud write point cloud instead without triangulation indices
-distance sets distance from shape into the range [0, Value];
-density sets density of points to generate randomly on surface;
-tolerance sets tolerance; default value is Precision::Confusion();
)", __FILE__, WritePly, g);
theCommands.Add ("writeply",
"writeply shape file",
__FILE__, WritePly, g);
}
//==============================================================================

View File

@@ -5,4 +5,3 @@
005 gltf_lateload
006 obj_read
007 obj_write
008 ply_write

View File

@@ -1,14 +0,0 @@
puts "============"
puts "0029325: Modeling Algorithms - add tool BRepLib_PointCloudShape for generation point cloud for specified shape"
puts "============"
puts ""
pload XDE OCAF MODELING VISUALIZATION
set aNbPntsExpected 32581
set aTmpPly ${imagedir}/${casename}_tmp.ply
lappend occ_tmp_files $aTmpPly
restore [locate_data_file bug29325_EQUERRE.brep] aShape
set aNbPnts [writeply aShape $aTmpPly -pointCloud -dist 0.0 -dens 0.1 -colors 0]
if {$aNbPnts != $aNbPntsExpected} { puts "Error: ($aNbPnts) generated while expected ($aNbPntsExpected)" }

View File

@@ -1,14 +0,0 @@
puts "============"
puts "0029325: Modeling Algorithms - add tool BRepLib_PointCloudShape for generation point cloud for specified shape"
puts "============"
puts ""
pload XDE OCAF MODELING VISUALIZATION
set aNbPntsExpected 27890
set aTmpPly ${imagedir}/${casename}_tmp.ply
lappend occ_tmp_files $aTmpPly
restore [locate_data_file bug29325_SANGLE_DE_FIXATION.brep] aShape
set aNbPnts [writeply aShape $aTmpPly -pointCloud -dist 0.0 -dens 0.5 -colors 0]
if {$aNbPnts != $aNbPntsExpected} { puts "Error: ($aNbPnts) generated while expected ($aNbPntsExpected)" }

View File

@@ -21,7 +21,7 @@ vrotate 0.2 0.0 0.0
vdump $::imagedir/${::casename}_green.png
# random colors mode
vpointcloud p s -randcolors -nonormals
vpointcloud p s -randcolors
vdump $::imagedir/${::casename}_rand.png
# texture mapping