f6469c539047cad1be5a03c10cd419143ed9bee3
[occt.git] / src / Poly / Poly.cxx
1 // File:        Poly.cxx
2 // Created:     Mon Mar  6 11:02:24 1995
3 // Author:      Laurent PAINNOT
4 //              <lpa@metrox>
5
6 #include <Standard_Stream.hxx>
7 #include <Poly.ixx>
8 #include <gp_Pnt.hxx>
9 #include <gp_Pnt2d.hxx>
10 #include <Poly_Triangle.hxx>
11 #include <TColgp_Array1OfPnt.hxx>
12 #include <TColgp_Array1OfPnt.hxx>
13 #include <TColStd_Array1OfReal.hxx>
14 #include <Poly_Array1OfTriangle.hxx>
15 #include <Poly_ListOfTriangulation.hxx>
16
17 #include <Poly_Polygon3D.hxx>
18 #include <Poly_Polygon2D.hxx>
19 #include <Precision.hxx>
20 #include <TShort_Array1OfShortReal.hxx>
21 #include <TShort_HArray1OfShortReal.hxx>
22
23 //=======================================================================
24 //function : Catenate
25 //purpose  : Join several triangulations to one new triangulation object
26 //=======================================================================
27
28 Handle(Poly_Triangulation) Poly::Catenate
29                         (const Poly_ListOfTriangulation& lstTri)
30 {
31   Standard_Integer nNodes(0);
32   Standard_Integer nTrian(0);
33
34   // Sum up the total number of nodes.
35   Poly_ListOfTriangulation::Iterator anIter(lstTri);
36   for (; anIter.More(); anIter.Next()) {
37     const Handle(Poly_Triangulation)& aTri = anIter.Value();
38     if (aTri.IsNull() == Standard_False) {
39       nNodes += aTri->NbNodes();
40       nTrian += aTri->NbTriangles();
41     }
42   }
43
44   Handle(Poly_Triangulation) aResult;
45   if (nNodes > 0) {
46     aResult = new Poly_Triangulation(nNodes, nTrian, Standard_False);
47     Standard_Integer i, iNode[3];
48     nNodes = 0;
49     nTrian = 0;
50     TColgp_Array1OfPnt&    arrNode  = aResult->ChangeNodes();
51     Poly_Array1OfTriangle& arrTrian = aResult->ChangeTriangles();
52     for (anIter.Init(lstTri); anIter.More(); anIter.Next()) {
53       const Handle(Poly_Triangulation)& aTri = anIter.Value();
54       if (aTri.IsNull() == Standard_False) {
55         const TColgp_Array1OfPnt&    srcNode  = aTri->Nodes();
56         const Poly_Array1OfTriangle& srcTrian = aTri->Triangles();
57         const Standard_Integer nbNodes = aTri->NbNodes(); 
58         const Standard_Integer nbTrian = aTri->NbTriangles(); 
59         for (i = 1; i <= nbNodes; i++) {
60           arrNode.SetValue(i + nNodes, srcNode(i));
61         }
62         for (i = 1; i <= nbTrian; i++) {
63           srcTrian(i).Get(iNode[0], iNode[1], iNode[2]);
64           arrTrian.SetValue(i + nTrian, Poly_Triangle(iNode[0] + nNodes,
65                                                       iNode[1] + nNodes,
66                                                       iNode[2] + nNodes));
67         }
68         nNodes += nbNodes;
69         nTrian += nbTrian;
70       }
71     }
72   }
73   return aResult;
74 }
75
76 //=======================================================================
77 //function : Write
78 //purpose  : 
79 //=======================================================================
80
81 void Poly::Write(const Handle(Poly_Triangulation)& T, 
82                  Standard_OStream& OS, 
83                  const Standard_Boolean Compact)
84 {
85   OS << "Poly_Triangulation\n";
86   if (Compact) {
87     OS << T->NbNodes() << " " << T->NbTriangles() << " ";
88     OS << ((T->HasUVNodes()) ? "1" : "0") << "\n";
89   }
90   else {
91     OS << setw(8) << T->NbNodes() << " Nodes\n";
92     OS << setw(8) << T->NbTriangles() << " Triangles\n";
93     OS << ((T->HasUVNodes()) ? "with" : "without") << " UV nodes\n";
94   }
95
96   // write the deflection
97
98   if (!Compact) OS << "Deflection : ";
99   OS << T->Deflection() << "\n";
100
101   // write the 3d nodes
102
103   if (!Compact) OS << "\n3D Nodes :\n";
104
105   Standard_Integer i, nbNodes = T->NbNodes();
106   const TColgp_Array1OfPnt& Nodes = T->Nodes();
107   for (i = 1; i <= nbNodes; i++) {
108     if (!Compact) OS << setw(10) << i << " : ";
109     if (!Compact) OS << setw(17);
110     OS << Nodes(i).X() << " ";
111     if (!Compact) OS << setw(17);
112     OS << Nodes(i).Y() << " ";
113     if (!Compact) OS << setw(17);
114     OS << Nodes(i).Z() << "\n";
115   }
116
117   if (T->HasUVNodes()) {
118     if (!Compact) OS << "\nUV Nodes :\n";
119     const TColgp_Array1OfPnt2d& UVNodes = T->UVNodes();
120     for (i = 1; i <= nbNodes; i++) {
121       if (!Compact) OS << setw(10) << i << " : ";
122     if (!Compact) OS << setw(17);
123       OS << UVNodes(i).X() << " ";
124     if (!Compact) OS << setw(17);
125       OS << UVNodes(i).Y() << "\n";
126     }
127   }
128       
129   if (!Compact) OS << "\nTriangles :\n";
130   Standard_Integer nbTriangles = T->NbTriangles();
131   Standard_Integer n1, n2, n3;
132   const Poly_Array1OfTriangle& Triangles = T->Triangles();
133   for (i = 1; i <= nbTriangles; i++) {
134     if (!Compact) OS << setw(10) << i << " : ";
135     Triangles(i).Get(n1, n2, n3);
136     if (!Compact) OS << setw(10);
137     OS << n1 << " ";
138     if (!Compact) OS << setw(10);
139     OS << n2 << " ";
140     if (!Compact) OS << setw(10);
141     OS << n3 << "\n";
142   }
143
144 }
145
146 //=======================================================================
147 //function : Write
148 //purpose  : 
149 //=======================================================================
150
151 void Poly::Write(const Handle(Poly_Polygon3D)& P, 
152                  Standard_OStream&             OS, 
153                  const Standard_Boolean        Compact)
154 {
155   OS << "Poly_Polygon3D\n";
156   if (Compact) {
157     OS << P->NbNodes() << " ";
158     OS << ((P->HasParameters()) ? "1" : "0") << "\n";
159   }
160   else {
161     OS << setw(8) << P->NbNodes() << " Nodes\n";
162     OS << ((P->HasParameters()) ? "with" : "without") << " parameters\n";
163   }
164
165   // write the deflection
166
167   if (!Compact) OS << "Deflection : ";
168   OS << P->Deflection() << "\n";
169
170   // write the nodes
171
172   if (!Compact) OS << "\nNodes :\n";
173
174   Standard_Integer i, nbNodes = P->NbNodes();
175   const TColgp_Array1OfPnt& Nodes = P->Nodes();
176   for (i = 1; i <= nbNodes; i++) {
177     if (!Compact) OS << setw(10) << i << " : ";
178     if (!Compact) OS << setw(17);
179     OS << Nodes(i).X() << " ";
180     if (!Compact) OS << setw(17);
181     OS << Nodes(i).Y() << " ";
182     if (!Compact) OS << setw(17);
183     OS << Nodes(i).Z() << "\n";
184   }
185
186   if (P->HasParameters()) {
187     if (!Compact) OS << "\nParameters :\n";
188     const TColStd_Array1OfReal& Param = P->Parameters();
189     for (i = 1; i <= nbNodes; i++) {
190       OS << Param(i) << " ";
191     }
192     OS <<"\n";
193   }
194
195
196 }
197
198
199 //=======================================================================
200 //function : Write
201 //purpose  : 
202 //=======================================================================
203
204 void Poly::Write(const Handle(Poly_Polygon2D)& P, 
205                  Standard_OStream&             OS, 
206                  const Standard_Boolean        Compact)
207 {
208   OS << "Poly_Polygon2D\n";
209   if (Compact) {
210     OS << P->NbNodes() << " ";
211   }
212   else {
213     OS << setw(8) << P->NbNodes() << " Nodes\n";
214   }
215
216   // write the deflection
217
218   if (!Compact) OS << "Deflection : ";
219   OS << P->Deflection() << "\n";
220
221   // write the nodes
222
223   if (!Compact) OS << "\nNodes :\n";
224
225   Standard_Integer i, nbNodes = P->NbNodes();
226   const TColgp_Array1OfPnt2d& Nodes = P->Nodes();
227   for (i = 1; i <= nbNodes; i++) {
228     if (!Compact) OS << setw(10) << i << " : ";
229     if (!Compact) OS << setw(17);
230     OS << Nodes(i).X() << " ";
231     if (!Compact) OS << setw(17);
232     OS << Nodes(i).Y() << "\n";
233   }
234 }
235
236
237
238 //=======================================================================
239 //function : Dump
240 //purpose  : 
241 //=======================================================================
242
243 void Poly::Dump(const Handle(Poly_Triangulation)& T, Standard_OStream& OS)
244 {
245   Poly::Write(T,OS,Standard_False);
246 }
247
248
249 //=======================================================================
250 //function : Dump
251 //purpose  : 
252 //=======================================================================
253
254 void Poly::Dump(const Handle(Poly_Polygon3D)& P, Standard_OStream& OS)
255 {
256   Poly::Write(P,OS,Standard_False);
257 }
258
259
260 //=======================================================================
261 //function : Dump
262 //purpose  : 
263 //=======================================================================
264
265 void Poly::Dump(const Handle(Poly_Polygon2D)& P, Standard_OStream& OS)
266 {
267   Poly::Write(P,OS,Standard_False);
268 }
269
270
271 //=======================================================================
272 //function : ReadTriangulation
273 //purpose  : 
274 //=======================================================================
275
276 Handle(Poly_Triangulation) Poly::ReadTriangulation(Standard_IStream& IS)
277 {
278   // Read a triangulation
279   
280   char line[100];
281   IS >> line;
282   if (strcmp(line,"Poly_Triangulation")) {
283     cout << "Not a Triangulation in the file" << endl;
284     return Handle(Poly_Triangulation)();
285   }
286
287   Standard_Integer nbNodes, nbTriangles;
288   Standard_Boolean hasUV;
289   IS >> nbNodes >> nbTriangles >> hasUV;
290
291   Standard_Real d;
292   IS >> d;
293
294   // read the 3d nodes
295   Standard_Real x,y,z;
296   Standard_Integer i;
297   TColgp_Array1OfPnt Nodes(1, nbNodes);
298   TColgp_Array1OfPnt2d UVNodes(1, nbNodes);
299
300   for (i = 1; i <= nbNodes; i++) {
301     IS >> x >> y >> z;
302     Nodes(i).SetCoord(x,y,z);
303   }
304
305   // read the UV points if necessary
306
307   if (hasUV) {
308     for (i = 1; i <= nbNodes; i++) {
309       IS >> x >> y;
310       UVNodes(i).SetCoord(x,y);
311     }
312   }
313
314
315   // read the triangles
316   Standard_Integer n1,n2,n3;
317   Poly_Array1OfTriangle Triangles(1, nbTriangles);
318   for (i = 1; i <= nbTriangles; i++) {
319     IS >> n1 >> n2 >> n3;
320     Triangles(i).Set(n1,n2,n3);
321   }
322
323   
324   Handle(Poly_Triangulation) T;
325
326   if (hasUV) T =  new Poly_Triangulation(Nodes,UVNodes,Triangles);
327   else T = new Poly_Triangulation(Nodes,Triangles);
328
329   T->Deflection(d);
330
331   return T;
332 }
333
334
335 //=======================================================================
336 //function : ReadPolygon3D
337 //purpose  : 
338 //=======================================================================
339
340 Handle(Poly_Polygon3D) Poly::ReadPolygon3D(Standard_IStream& IS)
341 {
342   // Read a 3d polygon
343   
344   char line[100];
345   IS >> line;
346   if (strcmp(line,"Poly_Polygon3D")) {
347     cout << "Not a Polygon3D in the file" << endl;
348     return Handle(Poly_Polygon3D)();
349   }
350
351   Standard_Integer nbNodes;
352   IS >> nbNodes;
353
354   Standard_Boolean hasparameters;
355   IS >> hasparameters;
356
357   Standard_Real d;
358   IS >> d;
359
360   // read the nodes
361   Standard_Real x,y,z;
362   Standard_Integer i;
363   TColgp_Array1OfPnt Nodes(1, nbNodes);
364
365   for (i = 1; i <= nbNodes; i++) {
366     IS >> x >> y >> z;
367     Nodes(i).SetCoord(x,y,z);
368   }
369
370   TColStd_Array1OfReal Param(1,nbNodes);
371   if (hasparameters) {
372     for (i = 1; i <= nbNodes; i++) {
373       IS >> Param(i);
374     }
375   }
376
377   Handle(Poly_Polygon3D) P;
378   if (!hasparameters)
379     P = new Poly_Polygon3D(Nodes);
380   else 
381     P = new Poly_Polygon3D(Nodes, Param);
382
383   P->Deflection(d);
384
385   return P;
386 }
387
388 //=======================================================================
389 //function : ReadPolygon3D
390 //purpose  : 
391 //=======================================================================
392
393 Handle(Poly_Polygon2D) Poly::ReadPolygon2D(Standard_IStream& IS)
394 {
395   // Read a 2d polygon
396   
397   char line[100];
398   IS >> line;
399   if (strcmp(line,"Poly_Polygon2D")) {
400     cout << "Not a Polygon2D in the file" << endl;
401     return Handle(Poly_Polygon2D)();
402   }
403
404   Standard_Integer nbNodes;
405   IS >> nbNodes;
406
407   Standard_Real d;
408   IS >> d;
409
410   // read the nodes
411   Standard_Real x,y;
412   Standard_Integer i;
413   TColgp_Array1OfPnt2d Nodes(1, nbNodes);
414
415   for (i = 1; i <= nbNodes; i++) {
416     IS >> x >> y;
417     Nodes(i).SetCoord(x,y);
418   }
419
420   Handle(Poly_Polygon2D) P = 
421     new Poly_Polygon2D(Nodes);
422   
423   P->Deflection(d);
424
425   return P;
426 }
427
428 //=======================================================================
429 //function : ComputeNormals
430 //purpose  : 
431 //=======================================================================
432
433 void  Poly::ComputeNormals(const Handle(Poly_Triangulation)& Tri)
434 {
435   const TColgp_Array1OfPnt&     arrNodes = Tri->Nodes();
436   const Poly_Array1OfTriangle & arrTri   = Tri->Triangles();
437   Standard_Integer              nbNormVal  = Tri->NbNodes() * 3; 
438   const Handle(TShort_HArray1OfShortReal) Normals =
439     new TShort_HArray1OfShortReal(1, nbNormVal);
440   Normals->Init(0.F);
441
442   Standard_ShortReal            * arrNormal = &(Normals->ChangeValue(1));
443
444   Standard_Real                 aCoord[3];
445   Standard_Integer              iNode[3] = {0, 0, 0};
446   Standard_Integer              iN, iTri;
447   const Standard_Real eps2 = Precision::Confusion()*Precision::Confusion();
448
449   for (iTri = 1; iTri <= arrTri.Length(); iTri++) {
450     // Get the nodes of the current triangle
451     arrTri(iTri).Get (iNode[0], iNode[1], iNode[2]);
452       const gp_XYZ aVec[2] = {
453         arrNodes(iNode[1]).XYZ() - arrNodes(iNode[0]).XYZ(),
454         arrNodes(iNode[2]).XYZ() - arrNodes(iNode[0]).XYZ()
455       };
456
457     // Find the normal vector of the current triangle
458     gp_XYZ aNorm = aVec[0] ^ aVec[1];
459     const Standard_Real aMod = aNorm.SquareModulus();
460     if (aMod > eps2) {
461       aNorm /= sqrt(aMod);
462       aNorm.Coord (aCoord[0], aCoord[1], aCoord[2]);
463       iNode[0] = (iNode[0]-1)*3;
464       iNode[1] = (iNode[1]-1)*3;
465       iNode[2] = (iNode[2]-1)*3;
466       arrNormal[iNode[0]+0] += (Standard_ShortReal)aCoord[0];
467       arrNormal[iNode[0]+1] += (Standard_ShortReal)aCoord[1];
468       arrNormal[iNode[0]+2] += (Standard_ShortReal)aCoord[2];
469       arrNormal[iNode[1]+0] += (Standard_ShortReal)aCoord[0];
470       arrNormal[iNode[1]+1] += (Standard_ShortReal)aCoord[1];
471       arrNormal[iNode[1]+2] += (Standard_ShortReal)aCoord[2];
472       arrNormal[iNode[2]+0] += (Standard_ShortReal)aCoord[0];
473       arrNormal[iNode[2]+1] += (Standard_ShortReal)aCoord[1];
474       arrNormal[iNode[2]+2] += (Standard_ShortReal)aCoord[2];
475     }
476   }
477   // Normalize all vectors
478   for (iN = 0; iN < nbNormVal; iN+=3) {
479     Standard_Real aMod (arrNormal[iN+0]*arrNormal[iN+0] +
480                         arrNormal[iN+1]*arrNormal[iN+1] +
481                         arrNormal[iN+2]*arrNormal[iN+2]);
482     if (aMod < eps2) {
483       arrNormal[iN+0] = 0.f;
484       arrNormal[iN+1] = 0.f;
485       arrNormal[iN+2] = 1.f;
486     } else {
487       aMod = sqrt(aMod);
488       arrNormal[iN+0] = Standard_ShortReal(arrNormal[iN+0]/aMod);
489       arrNormal[iN+1] = Standard_ShortReal(arrNormal[iN+1]/aMod);
490       arrNormal[iN+2] = Standard_ShortReal(arrNormal[iN+2]/aMod);
491     }
492   }
493
494   Tri->SetNormals(Normals);
495 }