0024166: Unable to create file with "Save" menu of voxeldemo Qt sample
[occt.git] / src / VrmlData / VrmlData_IndexedFaceSet.cxx
CommitLineData
b311480e 1// Created on: 2006-11-04
2// Created by: Alexander GRIGORIEV
3// Copyright (c) 2006-2012 OPEN CASCADE SAS
4//
5// The content of this file is subject to the Open CASCADE Technology Public
6// License Version 6.5 (the "License"). You may not use the content of this file
7// except in compliance with the License. Please obtain a copy of the License
8// at http://www.opencascade.org and read it completely before using this file.
9//
10// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
11// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
12//
13// The Original Code and all software distributed under the License is
14// distributed on an "AS IS" basis, without warranty of any kind, and the
15// Initial Developer hereby disclaims all such warranties, including without
16// limitation, any warranties of merchantability, fitness for a particular
17// purpose or non-infringement. Please see the License for the specific terms
18// and conditions governing the rights and limitations under the License.
19
7fd59977 20
21
22#include <VrmlData_IndexedFaceSet.hxx>
23#include <VrmlData_InBuffer.hxx>
24#include <VrmlData_UnknownNode.hxx>
25#include <Poly_Triangulation.hxx>
26#include <BRep_TFace.hxx>
27#include <VrmlData_Coordinate.hxx>
28#include <VrmlData_Color.hxx>
29#include <VrmlData_Normal.hxx>
30#include <VrmlData_TextureCoordinate.hxx>
31#include <VrmlData_Scene.hxx>
32#include <Precision.hxx>
33#include <NCollection_Vector.hxx>
34#include <NCollection_DataMap.hxx>
35#include <Poly.hxx>
36#include <TShort_HArray1OfShortReal.hxx>
37
38#ifdef WNT
39#define _CRT_SECURE_NO_DEPRECATE
40#pragma warning (disable:4996)
41#endif
42
43IMPLEMENT_STANDARD_HANDLE (VrmlData_Faceted, VrmlData_Geometry)
44IMPLEMENT_STANDARD_RTTIEXT (VrmlData_Faceted, VrmlData_Geometry)
45IMPLEMENT_STANDARD_HANDLE (VrmlData_IndexedFaceSet, VrmlData_Faceted)
46IMPLEMENT_STANDARD_RTTIEXT (VrmlData_IndexedFaceSet, VrmlData_Faceted)
47
48//=======================================================================
49//function : readData
50//purpose :
51//=======================================================================
52
53VrmlData_ErrorStatus VrmlData_Faceted::readData (VrmlData_InBuffer& theBuffer)
54{
55 VrmlData_ErrorStatus aStatus (VrmlData_EmptyData);
56 Standard_Boolean aBool;
57 if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "ccw")) {
58 if (OK(aStatus, ReadBoolean (theBuffer, aBool)))
59 myIsCCW = aBool;
60 } else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "convex")) {
61 if (OK(aStatus, ReadBoolean (theBuffer, aBool)))
62 myIsConvex = aBool;
63 } else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "solid")) {
64 if (OK(aStatus, ReadBoolean (theBuffer, aBool)))
65 myIsSolid = aBool;
66 } else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "creaseAngle")) {
67 Standard_Real anAngle;
68 if (OK(aStatus, Scene().ReadReal (theBuffer, anAngle,
eafb234b 69 Standard_False, Standard_False))) {
7fd59977 70 if (anAngle < -Precision::Confusion()*0.001)
71 aStatus = VrmlData_IrrelevantNumber;
72 else
73 myCreaseAngle = anAngle;
eafb234b 74 }
7fd59977 75 }
76 return aStatus;
77}
78
79//=======================================================================
80//function : VrmlData_IndexedFaceSet::TShape
81//purpose :
82//=======================================================================
83
84const Handle(TopoDS_TShape)& VrmlData_IndexedFaceSet::TShape ()
85{
86 if (myNbPolygons == 0)
87 myTShape.Nullify();
88 else if (myIsModified) {
89 // Create an empty topological Face
90 const gp_XYZ * arrNodes = myCoords->Values();
91 Standard_Integer i, nTri(0);
92
93 NCollection_DataMap <int, int> mapNodeId;
94
95 // Count non-degenerated triangles
bd0b3e60 96 const int nNodes = (int)myCoords->Length();
7fd59977 97 for (i = 0; i < (int)myNbPolygons; i++) {
98 const Standard_Integer * arrIndice;
99 if (Polygon(i, arrIndice) == 3) {
14b04bd2 100 //Check indices for out of bound
101 if (arrIndice[0] < 0 ||
102 arrIndice[0] >= nNodes ||
103 arrIndice[1] >= nNodes ||
104 arrIndice[2] >= nNodes)
105 {
106 continue;
107 }
7fd59977 108 const gp_XYZ aVec[2] = {
109 arrNodes[arrIndice[1]] - arrNodes[arrIndice[0]],
110 arrNodes[arrIndice[2]] - arrNodes[arrIndice[0]]
111 };
112 if ((aVec[0] ^ aVec[1]).SquareModulus() >
08cd2f6b 113 Precision::SquareConfusion())
7fd59977 114 ++nTri;
115 else {
116 const_cast<Standard_Integer&> (arrIndice[0]) = -1;
117 continue;
118 }
119 }
120 if (mapNodeId.IsBound (arrIndice[0]) == Standard_False)
121 mapNodeId.Bind (arrIndice[0], 0);
122 if (mapNodeId.IsBound (arrIndice[1]) == Standard_False)
123 mapNodeId.Bind (arrIndice[1], 0);
124 if (mapNodeId.IsBound (arrIndice[2]) == Standard_False)
125 mapNodeId.Bind (arrIndice[2], 0);
126 }
127 const Standard_Integer nbNodes (mapNodeId.Extent());
bd754989
V
128 if (!nbNodes)
129 {
130 myIsModified = Standard_False;
131 myTShape.Nullify();
132 return myTShape;
133 }
134
7fd59977 135 Handle(Poly_Triangulation) aTriangulation =
bd754989 136 new Poly_Triangulation (nbNodes, nTri, Standard_False);
7fd59977 137 Handle(BRep_TFace) aFace = new BRep_TFace();
138 aFace->Triangulation (aTriangulation);
139 myTShape = aFace;
140
bd754989 141 // Copy the triangulation vertices
7fd59977 142 TColgp_Array1OfPnt& aNodes = aTriangulation->ChangeNodes();
bd754989
V
143 NCollection_DataMap <int, int>::Iterator anIterN(mapNodeId);
144 for (i = 1; anIterN.More(); anIterN.Next()) {
145 const int aKey = anIterN.Key();
146 const gp_XYZ& aNodePnt = arrNodes[aKey];
147 aNodes(i) = gp_Pnt (aNodePnt);
148 anIterN.ChangeValue() = i++;
149 }
150
151 // Copy the triangles. Only the triangle-type polygons are supported.
152 // In this loop we also get rid of any possible degenerated triangles.
7fd59977 153 Poly_Array1OfTriangle& aTriangles = aTriangulation->ChangeTriangles();
7fd59977 154 nTri = 0;
bd754989
V
155 for (i = 0; i < (int)myNbPolygons; i++) {
156 const Standard_Integer * arrIndice;
157 if (Polygon (i, arrIndice) == 3)
14b04bd2 158 if (arrIndice[0] >= 0 &&
159 arrIndice[0] < nNodes &&
160 arrIndice[1] < nNodes &&
161 arrIndice[2] < nNodes) // check to avoid previously skipped faces
bd754989
V
162 aTriangles(++nTri).Set (mapNodeId(arrIndice[0]),
163 mapNodeId(arrIndice[1]),
164 mapNodeId(arrIndice[2]));
165 }
7fd59977 166
bd754989
V
167 // Normals should be defined; if they are not, compute them
168 if (myNormals.IsNull ()) {
169 //aTriangulation->ComputeNormals();
170 Poly::ComputeNormals(aTriangulation);
7fd59977 171 }
172 else {
bd754989
V
173 // Copy the normals. Currently only normals-per-vertex are supported.
174 Handle(TShort_HArray1OfShortReal) Normals =
175 new TShort_HArray1OfShortReal (1, 3*nbNodes);
176 if (myNormalPerVertex) {
177 if (myArrNormalInd == 0L) {
178 NCollection_DataMap <int, int>::Iterator anIterNN (mapNodeId);
179 for (; anIterNN.More (); anIterNN.Next ()) {
180 Standard_Integer anIdx = (anIterNN.Value() - 1) * 3 + 1;
181 const gp_XYZ& aNormal = myNormals->Normal (anIterNN.Key ());
182 Normals->SetValue (anIdx + 0, Standard_ShortReal (aNormal.X ()));
183 Normals->SetValue (anIdx + 1, Standard_ShortReal (aNormal.Y ()));
184 Normals->SetValue (anIdx + 2, Standard_ShortReal (aNormal.Z ()));
185 }
cccf81ea 186 }
187 else
188 {
189 for (i = 0; i < (int)myNbPolygons; i++)
190 {
191 const Standard_Integer * arrNodes;
14b04bd2 192 if (Polygon(i, arrNodes) == 3 &&
193 arrNodes[0] >= 0 &&
194 arrNodes[0] < nNodes &&
195 arrNodes[1] < nNodes &&
196 arrNodes[2] < nNodes) // check to avoid previously skipped faces
cccf81ea 197 {
198 const Standard_Integer * arrIndice;
199 if (IndiceNormals(i, arrIndice) == 3) {
200 for (Standard_Integer j = 0; j < 3; j++) {
201 const gp_XYZ& aNormal = myNormals->Normal (arrIndice[j]);
202 Standard_Integer anInd = arrNodes[j] * 3 + 1;
203 Normals->SetValue (anInd + 0, Standard_ShortReal (aNormal.X()));
204 Normals->SetValue (anInd + 1, Standard_ShortReal (aNormal.Y()));
205 Normals->SetValue (anInd + 2, Standard_ShortReal (aNormal.Z()));
bd754989 206 }
cccf81ea 207 }
208 }
7fd59977 209 }
bd754989
V
210 }
211 } else {
212 //TODO ..
7fd59977 213 }
bd754989 214 aTriangulation->SetNormals(Normals);
7fd59977 215 }
bd754989
V
216
217 myIsModified = Standard_False;
7fd59977 218 }
219 return myTShape;
220}
221
222//=======================================================================
223//function : VrmlData_IndexedFaceSet::Clone
224//purpose :
225//=======================================================================
226
227Handle(VrmlData_Node) VrmlData_IndexedFaceSet::Clone
228 (const Handle(VrmlData_Node)& theOther) const
229{
230 Handle(VrmlData_IndexedFaceSet) aResult =
231 Handle(VrmlData_IndexedFaceSet)::DownCast (VrmlData_Node::Clone(theOther));
232 if (aResult.IsNull())
233 aResult =
234 new VrmlData_IndexedFaceSet(theOther.IsNull()? Scene(): theOther->Scene(),
235 Name());
236
237 if (&aResult->Scene() == &Scene()) {
238 aResult->SetCoordinates (myCoords);
239 aResult->SetNormals (myNormals);
240 aResult->SetColors (myColors);
241 aResult->SetPolygons (myNbPolygons, myArrPolygons);
242 aResult->SetNormalInd (myNbNormals, myArrNormalInd);
243 aResult->SetColorInd (myNbColors, myArrColorInd);
244 aResult->SetTextureCoordInd (myNbTextures, myArrTextureInd);
245 } else {
246 // Create a dummy node to pass the different Scene instance to methods Clone
247 const Handle(VrmlData_UnknownNode) aDummyNode =
248 new VrmlData_UnknownNode (aResult->Scene());
249 if (myCoords.IsNull() == Standard_False)
250 aResult->SetCoordinates (Handle(VrmlData_Coordinate)::DownCast
251 (myCoords->Clone (aDummyNode)));
252 if (myNormals.IsNull() == Standard_False)
253 aResult->SetNormals (Handle(VrmlData_Normal)::DownCast
254 (myNormals->Clone (aDummyNode)));
255 if (myColors.IsNull() == Standard_False)
256 aResult->SetColors (Handle(VrmlData_Color)::DownCast
257 (myColors->Clone (aDummyNode)));
258 //TODO: Replace the following lines with the relevant copying
259 aResult->SetPolygons (myNbPolygons, myArrPolygons);
260 aResult->SetNormalInd (myNbNormals, myArrNormalInd);
261 aResult->SetColorInd (myNbColors, myArrColorInd);
262 aResult->SetTextureCoordInd (myNbTextures, myArrTextureInd);
263 }
264 aResult->SetNormalPerVertex (myNormalPerVertex);
265 aResult->SetColorPerVertex (myColorPerVertex);
266 return aResult;
267}
268
269//=======================================================================
270//function : VrmlData_IndexedFaceSet::Read
271//purpose :
272//=======================================================================
273
274VrmlData_ErrorStatus VrmlData_IndexedFaceSet::Read(VrmlData_InBuffer& theBuffer)
275{
276 VrmlData_ErrorStatus aStatus;
277 const VrmlData_Scene& aScene = Scene();
278 while (OK(aStatus, VrmlData_Scene::ReadLine(theBuffer)))
279 {
280 if (OK(aStatus, VrmlData_Faceted::readData (theBuffer)))
281 continue;
282 if (aStatus != VrmlData_EmptyData)
283 break;
284 else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "colorPerVertex"))
285 aStatus = ReadBoolean (theBuffer, myColorPerVertex);
286 else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "normalPerVertex"))
287 aStatus = ReadBoolean (theBuffer, myNormalPerVertex);
288 else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "coordIndex"))
289 aStatus = aScene.ReadArrIndex (theBuffer, myArrPolygons, myNbPolygons);
290 else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "colorIndex"))
291 aStatus = aScene.ReadArrIndex (theBuffer, myArrColorInd, myNbColors);
292 else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "normalIndex"))
293 aStatus = aScene.ReadArrIndex (theBuffer, myArrNormalInd, myNbNormals);
294 else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "texCoordIndex"))
295 aStatus = aScene.ReadArrIndex (theBuffer, myArrTextureInd, myNbTextures);
296 // These four checks should be the last one to avoid their interference
297 // with the other tokens (e.g., coordIndex)
298 else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "texCoord"))
299 aStatus = ReadNode (theBuffer, myTxCoords,
300 STANDARD_TYPE(VrmlData_TextureCoordinate));
301 else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "color"))
302 aStatus = ReadNode (theBuffer, myColors,
303 STANDARD_TYPE(VrmlData_Color));
304 else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "coord"))
305 aStatus = ReadNode (theBuffer, myCoords,
306 STANDARD_TYPE(VrmlData_Coordinate));
307 else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "normal"))
308 aStatus = ReadNode (theBuffer, myNormals,
309 STANDARD_TYPE(VrmlData_Normal));
310 if (!OK(aStatus))
311 break;
312 }
313 // Read the terminating (closing) brace
314 if (OK(aStatus) || aStatus == VrmlData_EmptyData)
315 if (OK(aStatus, readBrace (theBuffer))) {
316 // Post-processing
317 ;
318 }
319 return aStatus;
320}
321
322// //=======================================================================
323// //function : dummyReadBrackets
324// //purpose : static (local) function
325// //=======================================================================
326
327// VrmlData_ErrorStatus dummyReadBrackets (VrmlData_InBuffer& theBuffer)
328// {
329// VrmlData_ErrorStatus aStatus;
330// Standard_Integer aLevelCounter (0);
331// // This loop searches for any opening bracket.
332// // Such bracket increments the level counter. A closing bracket decrements
333// // the counter. The loop terminates when the counter becomes zero.
334// while ((aStatus = VrmlData_Scene::ReadLine(theBuffer)) == VrmlData_StatusOK)
335// {
336// int aChar;
337// while ((aChar = theBuffer.LinePtr[0]) != '\0') {
338// theBuffer.LinePtr++;
339// if (aChar == '[') {
340// aLevelCounter++;
341// break;
342// } else if (aChar == ']') {
343// aLevelCounter--;
344// break;
345// }
346// }
347// if (aLevelCounter <= 0)
348// break;
349// }
350// return aStatus;
351// }
352
353//=======================================================================
354//function : IsDefault
355//purpose :
356//=======================================================================
357
358Standard_Boolean VrmlData_IndexedFaceSet::IsDefault () const
359{
360 Standard_Boolean aResult (Standard_True);
361 if (myNbPolygons)
362 aResult = Standard_False;
363 else if (myCoords.IsNull() == Standard_False)
364 aResult = myCoords->IsDefault();
365 return aResult;
366}
367
368//=======================================================================
369//function : Write
370//purpose :
371//=======================================================================
372
373VrmlData_ErrorStatus VrmlData_IndexedFaceSet::Write
374 (const char * thePrefix) const
375{
376 static char header[] = "IndexedFaceSet {";
377 const VrmlData_Scene& aScene = Scene();
378 VrmlData_ErrorStatus aStatus;
379 if (OK (aStatus, aScene.WriteLine (thePrefix, header, GlobalIndent()))) {
380
381 // Write the attributes of interface "VrmlData_Faceted"
382 if (IsCCW() == Standard_False)
383 aStatus = aScene.WriteLine ("ccw FALSE");
384 if (OK(aStatus) && IsSolid() == Standard_False)
385 aStatus = aScene.WriteLine ("solid FALSE");
386 if (OK(aStatus) && IsConvex() == Standard_False)
387 aStatus = aScene.WriteLine ("convex FALSE");
388 if (OK(aStatus) && CreaseAngle() > Precision::Confusion()) {
389 char buf[64];
91322f44 390 Sprintf (buf, "%.9g", CreaseAngle());
7fd59977 391 aStatus = aScene.WriteLine ("creaseAngle", buf);
392 }
393
394 if (OK(aStatus) && myCoords.IsNull() == Standard_False)
395 aStatus = aScene.WriteNode ("coord", myCoords);
396 if (OK(aStatus))
397 aStatus = aScene.WriteArrIndex ("coordIndex", myArrPolygons,myNbPolygons);
398
399 if (OK(aStatus) && myNormalPerVertex == Standard_False)
400 aStatus = aScene.WriteLine ("normalPerVertex FALSE");
401 if (OK(aStatus) && myNormals.IsNull() == Standard_False)
402 aStatus = aScene.WriteNode ("normal", myNormals);
403 if (OK(aStatus))
404 aStatus = aScene.WriteArrIndex ("normalIndex",myArrNormalInd,myNbNormals);
405
406 if (OK(aStatus) && myColorPerVertex == Standard_False)
407 aStatus = aScene.WriteLine ("colorPerVertex FALSE");
408 if (OK(aStatus) && myColors.IsNull() == Standard_False)
409 aStatus = aScene.WriteNode ("color", myColors);
410 if (OK(aStatus))
411 aStatus = aScene.WriteArrIndex ("colorIndex", myArrColorInd, myNbColors);
412
413 if (OK(aStatus) && myTxCoords.IsNull() == Standard_False)
414 aStatus = aScene.WriteNode ("texCoord", myTxCoords);
415 if (OK(aStatus))
416 aStatus = aScene.WriteArrIndex ("texCoordIndex", myArrTextureInd,
417 myNbTextures);
418
419 aStatus = WriteClosing();
420 }
421 return aStatus;
422}
423
424//=======================================================================
425//function : GetColor
426//purpose :
427//=======================================================================
428
429Quantity_Color VrmlData_IndexedFaceSet::GetColor
430 (const Standard_Integer /*iFace*/,
431 const Standard_Integer /*iVertex*/)
432{
433 //TODO
434 return Quantity_NOC_BLACK;
435}
436