mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-04-16 10:08:36 +03:00
0030421: Data Exchange - Standard_RangeError exception while reading VRML files with polygons
Import of arbitrary polygon is implemented in VrmlData_IndexedFaceSet. Class IFCCAFControl_Triangulator has been moved to BRepMesh_Triangulator. New Draw test /bugs/stlvrml/bug30421 is added.
This commit is contained in:
parent
0d7753d266
commit
5ae53d4986
284
src/BRepMesh/BRepMesh_Triangulator.cxx
Normal file
284
src/BRepMesh/BRepMesh_Triangulator.cxx
Normal file
@ -0,0 +1,284 @@
|
|||||||
|
// Created: 2017-12-28
|
||||||
|
//
|
||||||
|
// Copyright (c) 2017 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 <BRepMesh_Triangulator.hxx>
|
||||||
|
#include <Precision.hxx>
|
||||||
|
#include <ProjLib.hxx>
|
||||||
|
#include <Message.hxx>
|
||||||
|
#include <Message_Messenger.hxx>
|
||||||
|
#include <BRepMesh_Delaun.hxx>
|
||||||
|
|
||||||
|
#ifdef CHECK_PERF
|
||||||
|
#include <MoniTool_Timer.hxx>
|
||||||
|
#include <MoniTool_TimerSentry.hxx>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
//=======================================================================
|
||||||
|
//function : wireNodesNb
|
||||||
|
//purpose :
|
||||||
|
//=======================================================================
|
||||||
|
inline Standard_Integer wireNodesNb (const NCollection_List<TColStd_SequenceOfInteger>& theWires)
|
||||||
|
{
|
||||||
|
Standard_Integer nbNodes = 0;
|
||||||
|
NCollection_List<TColStd_SequenceOfInteger>::Iterator itW(theWires);
|
||||||
|
for (Standard_Integer i = 1; itW.More(); itW.Next(), i++)
|
||||||
|
{
|
||||||
|
nbNodes += itW.Value().Length();
|
||||||
|
}
|
||||||
|
|
||||||
|
return nbNodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
//=======================================================================
|
||||||
|
//function : appendTriangle
|
||||||
|
//purpose :
|
||||||
|
//=======================================================================
|
||||||
|
inline void appendTriangle (const int theNode1, const int theNode2, const int theNode3,
|
||||||
|
const TColStd_SequenceOfInteger& theW,
|
||||||
|
NCollection_List<Poly_Triangle>& thePolyTriangles)
|
||||||
|
{
|
||||||
|
const Poly_Triangle aT1(theW(theNode1) + 1, theW(theNode2) + 1, theW(theNode3) + 1);
|
||||||
|
thePolyTriangles.Append(aT1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//=======================================================================
|
||||||
|
//function : ToPolyTriangulation
|
||||||
|
//purpose :
|
||||||
|
//=======================================================================
|
||||||
|
Handle(Poly_Triangulation) BRepMesh_Triangulator::ToPolyTriangulation (
|
||||||
|
const TColgp_Array1OfPnt& theNodes,
|
||||||
|
const NCollection_List<Poly_Triangle>& thePolyTriangles)
|
||||||
|
{
|
||||||
|
Poly_Array1OfTriangle aTriangles (1, thePolyTriangles.Extent());
|
||||||
|
NCollection_List<Poly_Triangle>::Iterator itT(thePolyTriangles);
|
||||||
|
for (Standard_Integer i = 1; itT.More(); itT.Next(), i++)
|
||||||
|
{
|
||||||
|
aTriangles.SetValue(i, itT.Value());
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Poly_Triangulation(theNodes, aTriangles);
|
||||||
|
}
|
||||||
|
|
||||||
|
//=======================================================================
|
||||||
|
//function : Constructor
|
||||||
|
//purpose :
|
||||||
|
//=======================================================================
|
||||||
|
BRepMesh_Triangulator::BRepMesh_Triangulator (
|
||||||
|
const NCollection_Vector<gp_XYZ>& theXYZs,
|
||||||
|
const NCollection_List<TColStd_SequenceOfInteger>& theWires,
|
||||||
|
const gp_Dir& theNorm)
|
||||||
|
: myXYZs (theXYZs)
|
||||||
|
, myWires (theWires)
|
||||||
|
, myPlane (gp::Origin (), theNorm)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
//=======================================================================
|
||||||
|
//function : Perform
|
||||||
|
//purpose :
|
||||||
|
//=======================================================================
|
||||||
|
Standard_Boolean BRepMesh_Triangulator::Perform (NCollection_List<Poly_Triangle>& thePolyTriangles)
|
||||||
|
{
|
||||||
|
#ifdef CHECK_PERF
|
||||||
|
MoniTool_TimerSentry MTS01("BRepMesh_Triangulator::Perform");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (myMess.IsNull())
|
||||||
|
{
|
||||||
|
myMess = Message::DefaultMessenger();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (myWires.Extent() == 1)
|
||||||
|
{
|
||||||
|
const TColStd_SequenceOfInteger& aTmpWire = myWires.First();
|
||||||
|
if (aTmpWire.Length() < 5)
|
||||||
|
{
|
||||||
|
// prepare triangles from simple wire (3 or 4 points)
|
||||||
|
addTriange34(aTmpWire, thePolyTriangles);
|
||||||
|
return Standard_True;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!prepareMeshStructure ())
|
||||||
|
{
|
||||||
|
return Standard_False;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!triangulate (thePolyTriangles))
|
||||||
|
{
|
||||||
|
return Standard_False;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CHECK_PERF
|
||||||
|
MTS01.Stop();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return Standard_True;
|
||||||
|
}
|
||||||
|
|
||||||
|
//=======================================================================
|
||||||
|
//function : addTriange34
|
||||||
|
//purpose : auxilary for makeTrianglesUsingBRepMesh
|
||||||
|
//=======================================================================
|
||||||
|
void BRepMesh_Triangulator::addTriange34(
|
||||||
|
const TColStd_SequenceOfInteger& theW,
|
||||||
|
NCollection_List<Poly_Triangle>& thePolyTriangles)
|
||||||
|
{
|
||||||
|
// prepare triangles from simple wire (3 or 4 points)
|
||||||
|
if (theW.Length() == 3)
|
||||||
|
{
|
||||||
|
Poly_Triangle aT(theW(1) + 1, theW(2) + 1, theW(3) + 1);
|
||||||
|
thePolyTriangles.Append(aT);
|
||||||
|
}
|
||||||
|
else if (theW.Length() == 4)
|
||||||
|
{
|
||||||
|
Standard_Real d13 = (myXYZs.Value(theW(1)) - myXYZs.Value(theW(3))).SquareModulus();
|
||||||
|
Standard_Real d24 = (myXYZs.Value(theW(2)) - myXYZs.Value(theW(4))).SquareModulus();
|
||||||
|
Standard_Boolean use13 = Standard_True;
|
||||||
|
if (d24 < d13)
|
||||||
|
{
|
||||||
|
// additional check for inner corner
|
||||||
|
static int aPivotNodes[4] = { 2, 4, 1, 3 };
|
||||||
|
use13 = checkCondition (aPivotNodes, theW);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
static int aPivotNodes[4] = { 1, 3, 2, 4 };
|
||||||
|
use13 = !checkCondition (aPivotNodes, theW);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (use13)
|
||||||
|
{
|
||||||
|
appendTriangle (1, 2, 3, theW, thePolyTriangles);
|
||||||
|
appendTriangle (3, 4, 1, theW, thePolyTriangles);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
appendTriangle (1, 2, 4, theW, thePolyTriangles);
|
||||||
|
appendTriangle (2, 3, 4, theW, thePolyTriangles);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//=======================================================================
|
||||||
|
//function : checkCondition
|
||||||
|
//purpose : auxilary for addTriange34
|
||||||
|
//=======================================================================
|
||||||
|
Standard_Boolean BRepMesh_Triangulator::checkCondition(
|
||||||
|
const int (&theNodes)[4],
|
||||||
|
const TColStd_SequenceOfInteger& theW)
|
||||||
|
{
|
||||||
|
const gp_XYZ aV0 = myXYZs.Value(theW(theNodes[1])) - myXYZs.Value(theW(theNodes[0]));
|
||||||
|
const gp_XYZ aV1 = myXYZs.Value(theW(theNodes[2])) - myXYZs.Value(theW(theNodes[0]));
|
||||||
|
const gp_XYZ aV2 = myXYZs.Value(theW(theNodes[3])) - myXYZs.Value(theW(theNodes[0]));
|
||||||
|
|
||||||
|
const gp_XYZ aCross1 = aV0.Crossed(aV1);
|
||||||
|
const gp_XYZ aCross2 = aV0.Crossed(aV2);
|
||||||
|
return (aCross1.SquareModulus() < Precision::SquareConfusion() ||
|
||||||
|
aCross2.SquareModulus() < Precision::SquareConfusion() ||
|
||||||
|
gp_Dir(aCross1).IsEqual(gp_Dir(aCross2), 0.01));
|
||||||
|
}
|
||||||
|
|
||||||
|
//=======================================================================
|
||||||
|
//function : prepareMeshStructure
|
||||||
|
//purpose :
|
||||||
|
//=======================================================================
|
||||||
|
Standard_Boolean BRepMesh_Triangulator::prepareMeshStructure ()
|
||||||
|
{
|
||||||
|
myIndices = new IMeshData::VectorOfInteger (wireNodesNb(myWires));
|
||||||
|
myMeshStructure = new BRepMesh_DataStructureOfDelaun (new NCollection_IncAllocator);
|
||||||
|
|
||||||
|
// fill this structure created BRepMesh_Vertexes using 2d points recieved
|
||||||
|
// by projection initial 3d point on plane.
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Standard_Integer aNumNode = 0;
|
||||||
|
NCollection_List<TColStd_SequenceOfInteger>::Iterator itW(myWires);
|
||||||
|
for (Standard_Integer i = 1; itW.More(); itW.Next(), i++)
|
||||||
|
{
|
||||||
|
const TColStd_SequenceOfInteger& aW = itW.Value();
|
||||||
|
for (Standard_Integer nn = 1; nn <= aW.Length(); ++nn, ++aNumNode)
|
||||||
|
{
|
||||||
|
const gp_Pnt2d aP2d = ProjLib::Project(myPlane, gp_Pnt(myXYZs(aW(nn))));
|
||||||
|
const BRepMesh_Vertex aVertex(aP2d.XY(), aNumNode, BRepMesh_Frontier);
|
||||||
|
const Standard_Integer nnn = myMeshStructure->AddNode(aVertex);
|
||||||
|
myIndices->SetValue(aNumNode, nnn);
|
||||||
|
myTmpMap.Bind(aNumNode + 1, aW(nn) + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const Standard_Integer aOffset = aNumNode - aW.Length ();
|
||||||
|
for (Standard_Integer nn = 1; nn <= aW.Length (); ++nn)
|
||||||
|
{
|
||||||
|
const BRepMesh_Edge anEdge(myIndices->Value(aOffset + (nn - 1)),
|
||||||
|
myIndices->Value(aOffset + (nn % aW.Length ())), BRepMesh_Frontier);
|
||||||
|
myMeshStructure->AddLink(anEdge);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
myMess->Send("makeTrianglesUsingBRepMesh: Exception raised during filling of BRepMesh_DataStructureOfDelaun", Message_Fail);
|
||||||
|
return Standard_False;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Standard_True;
|
||||||
|
}
|
||||||
|
|
||||||
|
//=======================================================================
|
||||||
|
//function : triangulate
|
||||||
|
//purpose : auxilary
|
||||||
|
//=======================================================================
|
||||||
|
Standard_Boolean BRepMesh_Triangulator::triangulate (NCollection_List<Poly_Triangle>& thePolyTriangles)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// perform triangulation used created aMeshStructure
|
||||||
|
BRepMesh_Delaun aTriangulation(myMeshStructure, *myIndices);
|
||||||
|
const IMeshData::MapOfInteger& aTriangles = myMeshStructure->ElementsOfDomain();
|
||||||
|
if (aTriangles.Extent() < 1)
|
||||||
|
{
|
||||||
|
return Standard_False;
|
||||||
|
}
|
||||||
|
|
||||||
|
// prepare Poly_Triangles from result triangles and add to returned list
|
||||||
|
for (IMeshData::IteratorOfMapOfInteger aTriIter(aTriangles); aTriIter.More(); aTriIter.Next())
|
||||||
|
{
|
||||||
|
const Standard_Integer aTriangleId = aTriIter.Key();
|
||||||
|
const BRepMesh_Triangle& aTriangle = myMeshStructure->GetElement(aTriangleId);
|
||||||
|
if (aTriangle.Movability() == BRepMesh_Deleted)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Standard_Integer aTri2d[3];
|
||||||
|
myMeshStructure->ElementNodes(aTriangle, aTri2d);
|
||||||
|
|
||||||
|
const Poly_Triangle aT(myTmpMap.Find(aTri2d[0]), myTmpMap.Find(aTri2d[1]), myTmpMap.Find(aTri2d[2]));
|
||||||
|
thePolyTriangles.Append(aT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Standard_Failure const& aFailure)
|
||||||
|
{
|
||||||
|
TCollection_AsciiString aStr("makeTrianglesUsingBRepMesh: Exception raised during polygon triangulation: ");
|
||||||
|
aStr.AssignCat(aFailure.GetMessageString());
|
||||||
|
myMess->Send(aStr.ToCString(), Message_Fail);
|
||||||
|
return Standard_False;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Standard_True;
|
||||||
|
}
|
96
src/BRepMesh/BRepMesh_Triangulator.hxx
Normal file
96
src/BRepMesh/BRepMesh_Triangulator.hxx
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
// Created: 2017-12-28
|
||||||
|
//
|
||||||
|
// Copyright (c) 2017 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 _BRepMesh_Triangulator_HeaderFile
|
||||||
|
#define _BRepMesh_Triangulator_HeaderFile
|
||||||
|
|
||||||
|
#include <gp_XYZ.hxx>
|
||||||
|
#include <gp_Dir.hxx>
|
||||||
|
#include <gp_Pln.hxx>
|
||||||
|
#include <Poly_Triangle.hxx>
|
||||||
|
#include <Poly_Triangulation.hxx>
|
||||||
|
#include <IMeshData_Types.hxx>
|
||||||
|
#include <NCollection_Vector.hxx>
|
||||||
|
#include <NCollection_List.hxx>
|
||||||
|
#include <NCollection_Shared.hxx>
|
||||||
|
#include <TColStd_SequenceOfInteger.hxx>
|
||||||
|
#include <TColStd_DataMapOfIntegerInteger.hxx>
|
||||||
|
#include <BRepMesh_DataStructureOfDelaun.hxx>
|
||||||
|
|
||||||
|
class Message_Messenger;
|
||||||
|
|
||||||
|
//! Auxilary tool to generate triangulation
|
||||||
|
class BRepMesh_Triangulator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
DEFINE_STANDARD_ALLOC
|
||||||
|
|
||||||
|
//! Performs conversion of the given list of triangles to Poly_Triangulation.
|
||||||
|
Standard_EXPORT static Handle(Poly_Triangulation) ToPolyTriangulation(
|
||||||
|
const TColgp_Array1OfPnt& theNodes,
|
||||||
|
const NCollection_List<Poly_Triangle>& thePolyTriangles);
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
//! Constructor. Initialized tool by the given parameters.
|
||||||
|
Standard_EXPORT BRepMesh_Triangulator (
|
||||||
|
const NCollection_Vector<gp_XYZ>& theXYZs,
|
||||||
|
const NCollection_List<TColStd_SequenceOfInteger>& theWires,
|
||||||
|
const gp_Dir& theNorm);
|
||||||
|
|
||||||
|
//! Perfroms triangulation of source wires and stores triangles the the output list.
|
||||||
|
Standard_EXPORT Standard_Boolean Perform (NCollection_List<Poly_Triangle>& thePolyTriangles);
|
||||||
|
|
||||||
|
//! Set messenger for output information
|
||||||
|
//! without this Message::DefaultMessenger() will be used
|
||||||
|
void SetMessenger(const Handle(Message_Messenger)& theMess)
|
||||||
|
{
|
||||||
|
myMess = theMess;
|
||||||
|
}
|
||||||
|
|
||||||
|
BRepMesh_Triangulator& operator =(const BRepMesh_Triangulator& theOther);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
// auxilary for makeTrianglesUsingBRepMesh
|
||||||
|
void addTriange34 (
|
||||||
|
const TColStd_SequenceOfInteger& theW,
|
||||||
|
NCollection_List<Poly_Triangle>& thePolyTriangles);
|
||||||
|
|
||||||
|
// auxilary for addTriange34
|
||||||
|
Standard_Boolean checkCondition(
|
||||||
|
const int (&theNodes)[4],
|
||||||
|
const TColStd_SequenceOfInteger& theWire);
|
||||||
|
|
||||||
|
// performs initialization of mesh data structure.
|
||||||
|
Standard_Boolean prepareMeshStructure();
|
||||||
|
|
||||||
|
// auxilary for triangulation
|
||||||
|
Standard_Boolean triangulate (NCollection_List<Poly_Triangle>& thePolyTriangles);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
const NCollection_Vector<gp_XYZ>& myXYZs;
|
||||||
|
const NCollection_List<TColStd_SequenceOfInteger>& myWires;
|
||||||
|
gp_Pln myPlane;
|
||||||
|
Handle(Message_Messenger) myMess;
|
||||||
|
|
||||||
|
Handle(BRepMesh_DataStructureOfDelaun) myMeshStructure;
|
||||||
|
TColStd_DataMapOfIntegerInteger myTmpMap;
|
||||||
|
Handle(IMeshData::VectorOfInteger) myIndices;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // _BRepMesh_Triangulator_HeaderFile
|
@ -94,3 +94,5 @@ BRepMesh_DelabellaBaseMeshAlgo.hxx
|
|||||||
BRepMesh_DelabellaBaseMeshAlgo.cxx
|
BRepMesh_DelabellaBaseMeshAlgo.cxx
|
||||||
BRepMesh_DelabellaMeshAlgoFactory.hxx
|
BRepMesh_DelabellaMeshAlgoFactory.hxx
|
||||||
BRepMesh_DelabellaMeshAlgoFactory.cxx
|
BRepMesh_DelabellaMeshAlgoFactory.cxx
|
||||||
|
BRepMesh_Triangulator.cxx
|
||||||
|
BRepMesh_Triangulator.hxx
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
#include <VrmlData_UnknownNode.hxx>
|
#include <VrmlData_UnknownNode.hxx>
|
||||||
#include <Poly_Triangulation.hxx>
|
#include <Poly_Triangulation.hxx>
|
||||||
#include <BRep_TFace.hxx>
|
#include <BRep_TFace.hxx>
|
||||||
|
#include <BRepMesh_Triangulator.hxx>
|
||||||
#include <VrmlData_Coordinate.hxx>
|
#include <VrmlData_Coordinate.hxx>
|
||||||
#include <VrmlData_Color.hxx>
|
#include <VrmlData_Color.hxx>
|
||||||
#include <VrmlData_Normal.hxx>
|
#include <VrmlData_Normal.hxx>
|
||||||
@ -28,6 +29,8 @@
|
|||||||
#include <NCollection_DataMap.hxx>
|
#include <NCollection_DataMap.hxx>
|
||||||
#include <Poly.hxx>
|
#include <Poly.hxx>
|
||||||
#include <TShort_HArray1OfShortReal.hxx>
|
#include <TShort_HArray1OfShortReal.hxx>
|
||||||
|
#include <TColgp_SequenceOfXYZ.hxx>
|
||||||
|
#include <TColStd_SequenceOfInteger.hxx>
|
||||||
|
|
||||||
IMPLEMENT_STANDARD_RTTIEXT(VrmlData_IndexedFaceSet,VrmlData_Faceted)
|
IMPLEMENT_STANDARD_RTTIEXT(VrmlData_IndexedFaceSet,VrmlData_Faceted)
|
||||||
|
|
||||||
@ -78,138 +81,198 @@ VrmlData_ErrorStatus VrmlData_Faceted::readData (VrmlData_InBuffer& theBuffer)
|
|||||||
const Handle(TopoDS_TShape)& VrmlData_IndexedFaceSet::TShape ()
|
const Handle(TopoDS_TShape)& VrmlData_IndexedFaceSet::TShape ()
|
||||||
{
|
{
|
||||||
if (myNbPolygons == 0)
|
if (myNbPolygons == 0)
|
||||||
|
{
|
||||||
myTShape.Nullify();
|
myTShape.Nullify();
|
||||||
else if (myIsModified) {
|
return myTShape;
|
||||||
// Create an empty topological Face
|
}
|
||||||
const gp_XYZ * arrNodes = myCoords->Values();
|
else if (!myIsModified) {
|
||||||
Standard_Integer i, nTri(0);
|
return myTShape;
|
||||||
|
}
|
||||||
|
|
||||||
NCollection_DataMap <int, int> mapNodeId;
|
// list of nodes:
|
||||||
|
const gp_XYZ * arrNodes = myCoords->Values();
|
||||||
|
const int nNodes = (int)myCoords->Length();
|
||||||
|
|
||||||
// Count non-degenerated triangles
|
NCollection_Map <int> mapNodeId;
|
||||||
const int nNodes = (int)myCoords->Length();
|
NCollection_Map <int> mapPolyId;
|
||||||
for (i = 0; i < (int)myNbPolygons; i++) {
|
NCollection_List<TColStd_SequenceOfInteger> aPolygons;
|
||||||
const Standard_Integer * arrIndice;
|
NCollection_List<gp_Dir> aNorms;
|
||||||
if (Polygon(i, arrIndice) == 3) {
|
Standard_Integer i = 0;
|
||||||
//Check indices for out of bound
|
for (; i < (int)myNbPolygons; i++)
|
||||||
if (arrIndice[0] < 0 ||
|
{
|
||||||
arrIndice[0] >= nNodes ||
|
const Standard_Integer * arrIndice = myArrPolygons[i];
|
||||||
arrIndice[1] >= nNodes ||
|
Standard_Integer nn = arrIndice[0];
|
||||||
arrIndice[2] >= nNodes)
|
if (nn < 3)
|
||||||
|
{
|
||||||
|
// bad polygon
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
TColStd_SequenceOfInteger aPolygon;
|
||||||
|
int in = 1;
|
||||||
|
for (; in <= nn; in++)
|
||||||
|
{
|
||||||
|
if (arrIndice[in] > nNodes)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
aPolygon.Append(arrIndice[in]);
|
||||||
|
}
|
||||||
|
if (in <= nn)
|
||||||
|
{
|
||||||
|
// bad index of node in polygon
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// calculate normal
|
||||||
|
gp_XYZ aSum;
|
||||||
|
gp_XYZ aPrevP = arrNodes[aPolygon(1)];
|
||||||
|
for (in = 2; in < aPolygon.Length(); in++)
|
||||||
|
{
|
||||||
|
gp_XYZ aP1 = arrNodes[aPolygon(in)];
|
||||||
|
gp_XYZ aP2 = arrNodes[aPolygon(in + 1)];
|
||||||
|
gp_XYZ aV1 = aP1 - aPrevP;
|
||||||
|
gp_XYZ aV2 = aP2 - aPrevP;
|
||||||
|
gp_XYZ S = aV1.Crossed(aV2);
|
||||||
|
aSum += S;
|
||||||
|
}
|
||||||
|
if (aSum.Modulus() < Precision::Confusion())
|
||||||
|
{
|
||||||
|
// degenerate polygon
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
gp_Dir aNormal(aSum);
|
||||||
|
mapPolyId.Add(i);
|
||||||
|
aPolygons.Append(aPolygon);
|
||||||
|
aNorms.Append(aNormal);
|
||||||
|
// collect info about used indices
|
||||||
|
for (in = 1; in <= aPolygon.Length(); in++)
|
||||||
|
{
|
||||||
|
mapNodeId.Add(arrIndice[in]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const Standard_Integer nbNodes(mapNodeId.Extent());
|
||||||
|
if (!nbNodes)
|
||||||
|
{
|
||||||
|
myIsModified = Standard_False;
|
||||||
|
myTShape.Nullify();
|
||||||
|
return myTShape;
|
||||||
|
}
|
||||||
|
// prepare vector of nodes
|
||||||
|
NCollection_Vector<gp_XYZ> aNodes;
|
||||||
|
NCollection_DataMap <int, int> mapIdId;
|
||||||
|
for (i = 0; i < nNodes; i++)
|
||||||
|
{
|
||||||
|
if(mapNodeId.Contains(i))
|
||||||
|
{
|
||||||
|
const gp_XYZ& aN1 = arrNodes[i];
|
||||||
|
mapIdId.Bind(i, aNodes.Length());
|
||||||
|
aNodes.Append(aN1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// update polygon indices
|
||||||
|
NCollection_List<TColStd_SequenceOfInteger>::Iterator itP(aPolygons);
|
||||||
|
for (; itP.More(); itP.Next())
|
||||||
|
{
|
||||||
|
TColStd_SequenceOfInteger& aPolygon = itP.ChangeValue();
|
||||||
|
for (int in = 1; in <= aPolygon.Length(); in++)
|
||||||
|
{
|
||||||
|
Standard_Integer newIdx = mapIdId.Find(aPolygon.Value(in));
|
||||||
|
aPolygon.ChangeValue(in) = newIdx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// calculate triangles
|
||||||
|
NCollection_List<Poly_Triangle> aTriangles;
|
||||||
|
itP.Init(aPolygons);
|
||||||
|
for (NCollection_List<gp_Dir>::Iterator itN(aNorms); itP.More(); itP.Next(), itN.Next())
|
||||||
|
{
|
||||||
|
NCollection_List<Poly_Triangle> aTrias;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
NCollection_List<TColStd_SequenceOfInteger> aPList;
|
||||||
|
aPList.Append(itP.Value());
|
||||||
|
BRepMesh_Triangulator aTriangulator(aNodes, aPList, itN.Value());
|
||||||
|
aTriangulator.Perform(aTrias);
|
||||||
|
aTriangles.Append(aTrias);
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (aTriangles.IsEmpty())
|
||||||
|
{
|
||||||
|
return myTShape;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Triangulation creation
|
||||||
|
Handle(Poly_Triangulation) aTriangulation =
|
||||||
|
new Poly_Triangulation(aNodes.Length(), aTriangles.Extent(), Standard_False);
|
||||||
|
// Copy the triangulation vertices
|
||||||
|
TColgp_Array1OfPnt& aTNodes = aTriangulation->ChangeNodes();
|
||||||
|
for (i = 0; i < aNodes.Length(); i++)
|
||||||
|
{
|
||||||
|
aTNodes.SetValue(i + 1, gp_Pnt(aNodes(i)));
|
||||||
|
}
|
||||||
|
// Copy the triangles.
|
||||||
|
Poly_Array1OfTriangle& aTTriangles = aTriangulation->ChangeTriangles();
|
||||||
|
NCollection_List<Poly_Triangle>::Iterator itT(aTriangles);
|
||||||
|
for (i = 1; itT.More(); itT.Next(), i++)
|
||||||
|
{
|
||||||
|
aTTriangles.SetValue(i, itT.Value());
|
||||||
|
}
|
||||||
|
|
||||||
|
Handle(BRep_TFace) aFace = new BRep_TFace();
|
||||||
|
aFace->Triangulation(aTriangulation);
|
||||||
|
myTShape = aFace;
|
||||||
|
|
||||||
|
// Normals should be defined; if they are not, compute them
|
||||||
|
if (myNormals.IsNull()) {
|
||||||
|
Poly::ComputeNormals(aTriangulation);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Copy the normals. Currently only normals-per-vertex are supported.
|
||||||
|
Handle(TShort_HArray1OfShortReal) Normals =
|
||||||
|
new TShort_HArray1OfShortReal(1, 3 * nbNodes);
|
||||||
|
if (myNormalPerVertex) {
|
||||||
|
if (myArrNormalInd == 0L) {
|
||||||
|
for (i = 0; i < nbNodes; i++)
|
||||||
{
|
{
|
||||||
continue;
|
Standard_Integer anIdx = i * 3 + 1;
|
||||||
}
|
const gp_XYZ& aNormal = myNormals->Normal(i);
|
||||||
const gp_XYZ aVec[2] = {
|
Normals->SetValue(anIdx + 0, Standard_ShortReal(aNormal.X()));
|
||||||
arrNodes[arrIndice[1]] - arrNodes[arrIndice[0]],
|
Normals->SetValue(anIdx + 1, Standard_ShortReal(aNormal.Y()));
|
||||||
arrNodes[arrIndice[2]] - arrNodes[arrIndice[0]]
|
Normals->SetValue(anIdx + 2, Standard_ShortReal(aNormal.Z()));
|
||||||
};
|
|
||||||
if ((aVec[0] ^ aVec[1]).SquareModulus() >
|
|
||||||
Precision::SquareConfusion())
|
|
||||||
++nTri;
|
|
||||||
else {
|
|
||||||
const_cast<Standard_Integer&> (arrIndice[0]) = -1;
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (mapNodeId.IsBound (arrIndice[0]) == Standard_False)
|
else
|
||||||
mapNodeId.Bind (arrIndice[0], 0);
|
{
|
||||||
if (mapNodeId.IsBound (arrIndice[1]) == Standard_False)
|
for (i = 0; i < (int)myNbPolygons; i++)
|
||||||
mapNodeId.Bind (arrIndice[1], 0);
|
|
||||||
if (mapNodeId.IsBound (arrIndice[2]) == Standard_False)
|
|
||||||
mapNodeId.Bind (arrIndice[2], 0);
|
|
||||||
}
|
|
||||||
const Standard_Integer nbNodes (mapNodeId.Extent());
|
|
||||||
if (!nbNodes)
|
|
||||||
{
|
|
||||||
myIsModified = Standard_False;
|
|
||||||
myTShape.Nullify();
|
|
||||||
return myTShape;
|
|
||||||
}
|
|
||||||
|
|
||||||
Handle(Poly_Triangulation) aTriangulation =
|
|
||||||
new Poly_Triangulation (nbNodes, nTri, Standard_False);
|
|
||||||
Handle(BRep_TFace) aFace = new BRep_TFace();
|
|
||||||
aFace->Triangulation (aTriangulation);
|
|
||||||
myTShape = aFace;
|
|
||||||
|
|
||||||
// Copy the triangulation vertices
|
|
||||||
TColgp_Array1OfPnt& aNodes = aTriangulation->ChangeNodes();
|
|
||||||
NCollection_DataMap <int, int>::Iterator anIterN(mapNodeId);
|
|
||||||
for (i = 1; anIterN.More(); anIterN.Next()) {
|
|
||||||
const int aKey = anIterN.Key();
|
|
||||||
const gp_XYZ& aNodePnt = arrNodes[aKey];
|
|
||||||
aNodes(i) = gp_Pnt (aNodePnt);
|
|
||||||
anIterN.ChangeValue() = i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy the triangles. Only the triangle-type polygons are supported.
|
|
||||||
// In this loop we also get rid of any possible degenerated triangles.
|
|
||||||
Poly_Array1OfTriangle& aTriangles = aTriangulation->ChangeTriangles();
|
|
||||||
nTri = 0;
|
|
||||||
for (i = 0; i < (int)myNbPolygons; i++) {
|
|
||||||
const Standard_Integer * arrIndice;
|
|
||||||
if (Polygon (i, arrIndice) == 3)
|
|
||||||
if (arrIndice[0] >= 0 &&
|
|
||||||
arrIndice[0] < nNodes &&
|
|
||||||
arrIndice[1] < nNodes &&
|
|
||||||
arrIndice[2] < nNodes) // check to avoid previously skipped faces
|
|
||||||
aTriangles(++nTri).Set (mapNodeId(arrIndice[0]),
|
|
||||||
mapNodeId(arrIndice[1]),
|
|
||||||
mapNodeId(arrIndice[2]));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Normals should be defined; if they are not, compute them
|
|
||||||
if (myNormals.IsNull ()) {
|
|
||||||
//aTriangulation->ComputeNormals();
|
|
||||||
Poly::ComputeNormals(aTriangulation);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// Copy the normals. Currently only normals-per-vertex are supported.
|
|
||||||
Handle(TShort_HArray1OfShortReal) Normals =
|
|
||||||
new TShort_HArray1OfShortReal (1, 3*nbNodes);
|
|
||||||
if (myNormalPerVertex) {
|
|
||||||
if (myArrNormalInd == 0L) {
|
|
||||||
NCollection_DataMap <int, int>::Iterator anIterNN (mapNodeId);
|
|
||||||
for (; anIterNN.More (); anIterNN.Next ()) {
|
|
||||||
Standard_Integer anIdx = (anIterNN.Value() - 1) * 3 + 1;
|
|
||||||
const gp_XYZ& aNormal = myNormals->Normal (anIterNN.Key ());
|
|
||||||
Normals->SetValue (anIdx + 0, Standard_ShortReal (aNormal.X ()));
|
|
||||||
Normals->SetValue (anIdx + 1, Standard_ShortReal (aNormal.Y ()));
|
|
||||||
Normals->SetValue (anIdx + 2, Standard_ShortReal (aNormal.Z ()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
for (i = 0; i < (int)myNbPolygons; i++)
|
if(mapPolyId.Contains(i)) // check to avoid previously skipped faces
|
||||||
{
|
{
|
||||||
const Standard_Integer * anArrNodes;
|
const Standard_Integer * anArrNodes;
|
||||||
if (Polygon(i, anArrNodes) == 3 &&
|
Polygon(i, anArrNodes);
|
||||||
anArrNodes[0] >= 0 &&
|
const Standard_Integer * arrIndice;
|
||||||
anArrNodes[0] < nNodes &&
|
int nbn = IndiceNormals(i, arrIndice);
|
||||||
anArrNodes[1] < nNodes &&
|
for (Standard_Integer j = 0; j < nbn; j++) {
|
||||||
anArrNodes[2] < nNodes) // check to avoid previously skipped faces
|
const gp_XYZ& aNormal = myNormals->Normal(arrIndice[j]);
|
||||||
{
|
Standard_Integer anInd = mapIdId(anArrNodes[j]) * 3 + 1;
|
||||||
const Standard_Integer * arrIndice;
|
Normals->SetValue(anInd + 0, Standard_ShortReal(aNormal.X()));
|
||||||
if (IndiceNormals(i, arrIndice) == 3) {
|
Normals->SetValue(anInd + 1, Standard_ShortReal(aNormal.Y()));
|
||||||
for (Standard_Integer j = 0; j < 3; j++) {
|
Normals->SetValue(anInd + 2, Standard_ShortReal(aNormal.Z()));
|
||||||
const gp_XYZ& aNormal = myNormals->Normal (arrIndice[j]);
|
|
||||||
Standard_Integer anInd = (mapNodeId(anArrNodes[j]) - 1) * 3 + 1;
|
|
||||||
Normals->SetValue (anInd + 0, Standard_ShortReal (aNormal.X()));
|
|
||||||
Normals->SetValue (anInd + 1, Standard_ShortReal (aNormal.Y()));
|
|
||||||
Normals->SetValue (anInd + 2, Standard_ShortReal (aNormal.Z()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
//TODO ..
|
|
||||||
}
|
}
|
||||||
aTriangulation->SetNormals(Normals);
|
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
myIsModified = Standard_False;
|
//TODO ..
|
||||||
|
}
|
||||||
|
aTriangulation->SetNormals(Normals);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
myIsModified = Standard_False;
|
||||||
|
|
||||||
return myTShape;
|
return myTShape;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -279,8 +342,21 @@ VrmlData_ErrorStatus VrmlData_IndexedFaceSet::Read(VrmlData_InBuffer& theBuffer)
|
|||||||
aStatus = ReadBoolean (theBuffer, myColorPerVertex);
|
aStatus = ReadBoolean (theBuffer, myColorPerVertex);
|
||||||
else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "normalPerVertex"))
|
else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "normalPerVertex"))
|
||||||
aStatus = ReadBoolean (theBuffer, myNormalPerVertex);
|
aStatus = ReadBoolean (theBuffer, myNormalPerVertex);
|
||||||
else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "coordIndex"))
|
else if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "coordIndex"))
|
||||||
aStatus = aScene.ReadArrIndex (theBuffer, myArrPolygons, myNbPolygons);
|
{
|
||||||
|
aStatus = aScene.ReadArrIndex(theBuffer, myArrPolygons, myNbPolygons);
|
||||||
|
//for (int i = 0; i < myNbPolygons; i++)
|
||||||
|
//{
|
||||||
|
// const Standard_Integer * anArray = myArrPolygons[i];
|
||||||
|
// Standard_Integer nbPoints = anArray[0];
|
||||||
|
// std::cout << "i = " << i << " indexes:";
|
||||||
|
// for (int ip = 1; ip <= nbPoints; ip++)
|
||||||
|
// {
|
||||||
|
// std::cout << " " << anArray[ip];
|
||||||
|
// }
|
||||||
|
// std::cout << std::endl;
|
||||||
|
//}
|
||||||
|
}
|
||||||
else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "colorIndex"))
|
else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "colorIndex"))
|
||||||
aStatus = aScene.ReadArrIndex (theBuffer, myArrColorInd, myNbColors);
|
aStatus = aScene.ReadArrIndex (theBuffer, myArrColorInd, myNbColors);
|
||||||
else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "normalIndex"))
|
else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "normalIndex"))
|
||||||
|
@ -821,8 +821,19 @@ VrmlData_ErrorStatus VrmlData_Scene::ReadArrIndex
|
|||||||
isMore = Standard_False;
|
isMore = Standard_False;
|
||||||
}
|
}
|
||||||
if (anIntValue >= 0)
|
if (anIntValue >= 0)
|
||||||
|
{
|
||||||
|
if (vecInt.Length() > 2)
|
||||||
|
{
|
||||||
|
// additional check for redundant point:
|
||||||
|
// ignore last point which is a dublicate of first point
|
||||||
|
if (anIntValue == vecInt[0])
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
// The input value is a node index, store it in the buffer vector
|
// The input value is a node index, store it in the buffer vector
|
||||||
vecInt.Append (static_cast<Standard_Integer> (anIntValue));
|
vecInt.Append(static_cast<Standard_Integer> (anIntValue));
|
||||||
|
}
|
||||||
if ((anIntValue < 0 || isMore == Standard_False)
|
if ((anIntValue < 0 || isMore == Standard_False)
|
||||||
&& vecInt.Length() > 0)
|
&& vecInt.Length() > 0)
|
||||||
{
|
{
|
||||||
|
8
tests/bugs/stlvrml/bug30421
Normal file
8
tests/bugs/stlvrml/bug30421
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
puts "================"
|
||||||
|
puts "0030421: Data Exchange - Standard_RangeError e x c e p t i o n while reading VRML files with polygons"
|
||||||
|
puts "================"
|
||||||
|
puts ""
|
||||||
|
|
||||||
|
loadvrml result [locate_data_file bug30421.wrl]
|
||||||
|
|
||||||
|
checkview -display result -3d -path ${imagedir}/${test_image}.png
|
Loading…
x
Reference in New Issue
Block a user