diff --git a/src/BRepMesh/BRepMesh_Triangulator.cxx b/src/BRepMesh/BRepMesh_Triangulator.cxx new file mode 100644 index 0000000000..7d84feb019 --- /dev/null +++ b/src/BRepMesh/BRepMesh_Triangulator.cxx @@ -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 +#include +#include +#include +#include +#include + +#ifdef CHECK_PERF +#include +#include +#endif + +namespace +{ + //======================================================================= + //function : wireNodesNb + //purpose : + //======================================================================= + inline Standard_Integer wireNodesNb (const NCollection_List& theWires) + { + Standard_Integer nbNodes = 0; + NCollection_List::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& 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& thePolyTriangles) +{ + Poly_Array1OfTriangle aTriangles (1, thePolyTriangles.Extent()); + NCollection_List::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& theXYZs, + const NCollection_List& theWires, + const gp_Dir& theNorm) + : myXYZs (theXYZs) + , myWires (theWires) + , myPlane (gp::Origin (), theNorm) +{ +} + +//======================================================================= +//function : Perform +//purpose : +//======================================================================= +Standard_Boolean BRepMesh_Triangulator::Perform (NCollection_List& 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& 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::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& 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; +} diff --git a/src/BRepMesh/BRepMesh_Triangulator.hxx b/src/BRepMesh/BRepMesh_Triangulator.hxx new file mode 100644 index 0000000000..ad56df37cc --- /dev/null +++ b/src/BRepMesh/BRepMesh_Triangulator.hxx @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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& thePolyTriangles); + +public: + + //! Constructor. Initialized tool by the given parameters. + Standard_EXPORT BRepMesh_Triangulator ( + const NCollection_Vector& theXYZs, + const NCollection_List& theWires, + const gp_Dir& theNorm); + + //! Perfroms triangulation of source wires and stores triangles the the output list. + Standard_EXPORT Standard_Boolean Perform (NCollection_List& 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& 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& thePolyTriangles); + +private: + + const NCollection_Vector& myXYZs; + const NCollection_List& myWires; + gp_Pln myPlane; + Handle(Message_Messenger) myMess; + + Handle(BRepMesh_DataStructureOfDelaun) myMeshStructure; + TColStd_DataMapOfIntegerInteger myTmpMap; + Handle(IMeshData::VectorOfInteger) myIndices; +}; + +#endif // _BRepMesh_Triangulator_HeaderFile diff --git a/src/BRepMesh/FILES b/src/BRepMesh/FILES index 90df7c410b..d1d2fa3511 100755 --- a/src/BRepMesh/FILES +++ b/src/BRepMesh/FILES @@ -94,3 +94,5 @@ BRepMesh_DelabellaBaseMeshAlgo.hxx BRepMesh_DelabellaBaseMeshAlgo.cxx BRepMesh_DelabellaMeshAlgoFactory.hxx BRepMesh_DelabellaMeshAlgoFactory.cxx +BRepMesh_Triangulator.cxx +BRepMesh_Triangulator.hxx diff --git a/src/VrmlData/VrmlData_IndexedFaceSet.cxx b/src/VrmlData/VrmlData_IndexedFaceSet.cxx index 0e5f8c4fe8..a513281edb 100644 --- a/src/VrmlData/VrmlData_IndexedFaceSet.cxx +++ b/src/VrmlData/VrmlData_IndexedFaceSet.cxx @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -28,6 +29,8 @@ #include #include #include +#include +#include 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 () { if (myNbPolygons == 0) + { myTShape.Nullify(); - else if (myIsModified) { - // Create an empty topological Face - const gp_XYZ * arrNodes = myCoords->Values(); - Standard_Integer i, nTri(0); + return myTShape; + } + else if (!myIsModified) { + return myTShape; + } - NCollection_DataMap mapNodeId; + // list of nodes: + const gp_XYZ * arrNodes = myCoords->Values(); + const int nNodes = (int)myCoords->Length(); - // Count non-degenerated triangles - const int nNodes = (int)myCoords->Length(); - for (i = 0; i < (int)myNbPolygons; i++) { - const Standard_Integer * arrIndice; - if (Polygon(i, arrIndice) == 3) { - //Check indices for out of bound - if (arrIndice[0] < 0 || - arrIndice[0] >= nNodes || - arrIndice[1] >= nNodes || - arrIndice[2] >= nNodes) + NCollection_Map mapNodeId; + NCollection_Map mapPolyId; + NCollection_List aPolygons; + NCollection_List aNorms; + Standard_Integer i = 0; + for (; i < (int)myNbPolygons; i++) + { + const Standard_Integer * arrIndice = myArrPolygons[i]; + Standard_Integer nn = arrIndice[0]; + 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 aNodes; + NCollection_DataMap 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::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 aTriangles; + itP.Init(aPolygons); + for (NCollection_List::Iterator itN(aNorms); itP.More(); itP.Next(), itN.Next()) + { + NCollection_List aTrias; + try + { + NCollection_List 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::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; - } - const gp_XYZ aVec[2] = { - arrNodes[arrIndice[1]] - arrNodes[arrIndice[0]], - arrNodes[arrIndice[2]] - arrNodes[arrIndice[0]] - }; - if ((aVec[0] ^ aVec[1]).SquareModulus() > - Precision::SquareConfusion()) - ++nTri; - else { - const_cast (arrIndice[0]) = -1; - continue; + Standard_Integer anIdx = i * 3 + 1; + const gp_XYZ& aNormal = myNormals->Normal(i); + Normals->SetValue(anIdx + 0, Standard_ShortReal(aNormal.X())); + Normals->SetValue(anIdx + 1, Standard_ShortReal(aNormal.Y())); + Normals->SetValue(anIdx + 2, Standard_ShortReal(aNormal.Z())); } } - if (mapNodeId.IsBound (arrIndice[0]) == Standard_False) - mapNodeId.Bind (arrIndice[0], 0); - if (mapNodeId.IsBound (arrIndice[1]) == Standard_False) - 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 ::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 ::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 + else + { + for (i = 0; i < (int)myNbPolygons; i++) { - for (i = 0; i < (int)myNbPolygons; i++) + if(mapPolyId.Contains(i)) // check to avoid previously skipped faces { const Standard_Integer * anArrNodes; - if (Polygon(i, anArrNodes) == 3 && - anArrNodes[0] >= 0 && - anArrNodes[0] < nNodes && - anArrNodes[1] < nNodes && - anArrNodes[2] < nNodes) // check to avoid previously skipped faces - { - const Standard_Integer * arrIndice; - if (IndiceNormals(i, arrIndice) == 3) { - for (Standard_Integer j = 0; j < 3; j++) { - 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())); - } - } + Polygon(i, anArrNodes); + const Standard_Integer * arrIndice; + int nbn = IndiceNormals(i, arrIndice); + for (Standard_Integer j = 0; j < nbn; j++) { + const gp_XYZ& aNormal = myNormals->Normal(arrIndice[j]); + Standard_Integer anInd = mapIdId(anArrNodes[j]) * 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); } - - myIsModified = Standard_False; + else { + //TODO .. + } + aTriangulation->SetNormals(Normals); } + + myIsModified = Standard_False; + return myTShape; } @@ -279,8 +342,21 @@ VrmlData_ErrorStatus VrmlData_IndexedFaceSet::Read(VrmlData_InBuffer& theBuffer) aStatus = ReadBoolean (theBuffer, myColorPerVertex); else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "normalPerVertex")) aStatus = ReadBoolean (theBuffer, myNormalPerVertex); - else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "coordIndex")) - aStatus = aScene.ReadArrIndex (theBuffer, myArrPolygons, myNbPolygons); + else if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "coordIndex")) + { + 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")) aStatus = aScene.ReadArrIndex (theBuffer, myArrColorInd, myNbColors); else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "normalIndex")) diff --git a/src/VrmlData/VrmlData_Scene.cxx b/src/VrmlData/VrmlData_Scene.cxx index 60edbb97bb..332757ce2e 100644 --- a/src/VrmlData/VrmlData_Scene.cxx +++ b/src/VrmlData/VrmlData_Scene.cxx @@ -821,8 +821,19 @@ VrmlData_ErrorStatus VrmlData_Scene::ReadArrIndex isMore = Standard_False; } 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 - vecInt.Append (static_cast (anIntValue)); + vecInt.Append(static_cast (anIntValue)); + } if ((anIntValue < 0 || isMore == Standard_False) && vecInt.Length() > 0) { diff --git a/tests/bugs/stlvrml/bug30421 b/tests/bugs/stlvrml/bug30421 new file mode 100644 index 0000000000..793bbab92e --- /dev/null +++ b/tests/bugs/stlvrml/bug30421 @@ -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