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