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.
--- /dev/null
+// 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;
+}
--- /dev/null
+// 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
BRepMesh_DelabellaBaseMeshAlgo.cxx
BRepMesh_DelabellaMeshAlgoFactory.hxx
BRepMesh_DelabellaMeshAlgoFactory.cxx
+BRepMesh_Triangulator.cxx
+BRepMesh_Triangulator.hxx
#include <VrmlData_UnknownNode.hxx>
#include <Poly_Triangulation.hxx>
#include <BRep_TFace.hxx>
+#include <BRepMesh_Triangulator.hxx>
#include <VrmlData_Coordinate.hxx>
#include <VrmlData_Color.hxx>
#include <VrmlData_Normal.hxx>
#include <NCollection_DataMap.hxx>
#include <Poly.hxx>
#include <TShort_HArray1OfShortReal.hxx>
+#include <TColgp_SequenceOfXYZ.hxx>
+#include <TColStd_SequenceOfInteger.hxx>
IMPLEMENT_STANDARD_RTTIEXT(VrmlData_IndexedFaceSet,VrmlData_Faceted)
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);
-
- NCollection_DataMap <int, int> mapNodeId;
-
- // 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)
- {
- 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<Standard_Integer&> (arrIndice[0]) = -1;
- continue;
- }
+ return myTShape;
+ }
+ else if (!myIsModified) {
+ return myTShape;
+ }
+
+ // list of nodes:
+ const gp_XYZ * arrNodes = myCoords->Values();
+ const int nNodes = (int)myCoords->Length();
+
+ NCollection_Map <int> mapNodeId;
+ NCollection_Map <int> mapPolyId;
+ NCollection_List<TColStd_SequenceOfInteger> aPolygons;
+ NCollection_List<gp_Dir> 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;
}
- 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);
+ aPolygon.Append(arrIndice[in]);
}
- const Standard_Integer nbNodes (mapNodeId.Extent());
- if (!nbNodes)
+ if (in <= nn)
{
- myIsModified = Standard_False;
- myTShape.Nullify();
- return myTShape;
+ // bad index of node in polygon
+ continue;
}
-
- 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++;
+ // 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;
}
-
- // 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]));
+ 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]);
}
+ }
- // Normals should be defined; if they are not, compute them
- if (myNormals.IsNull ()) {
- //aTriangulation->ComputeNormals();
- Poly::ComputeNormals(aTriangulation);
+ 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);
}
- 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 ()));
- }
+ }
+ // 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++)
+ {
+ 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()));
}
- 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;
}
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"))
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<Standard_Integer> (anIntValue));
+ vecInt.Append(static_cast<Standard_Integer> (anIntValue));
+ }
if ((anIntValue < 0 || isMore == Standard_False)
&& vecInt.Length() > 0)
{
--- /dev/null
+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