0025936: Reusable data structure for 2D tesselation (3- and 4-nodal mesh)
[occt.git] / src / Poly / Poly.cxx
CommitLineData
b311480e 1// Created on: 1995-03-06
2// Created by: Laurent PAINNOT
3// Copyright (c) 1995-1999 Matra Datavision
973c2be1 4// Copyright (c) 1999-2014 OPEN CASCADE SAS
b311480e 5//
973c2be1 6// This file is part of Open CASCADE Technology software library.
b311480e 7//
d5f74e42 8// This library is free software; you can redistribute it and/or modify it under
9// the terms of the GNU Lesser General Public License version 2.1 as published
973c2be1 10// by the Free Software Foundation, with special exception defined in the file
11// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12// distribution for complete text of the license and disclaimer of any warranty.
b311480e 13//
973c2be1 14// Alternatively, this file may be used under the terms of Open CASCADE
15// commercial license or contractual agreement.
7fd59977 16
17#include <Standard_Stream.hxx>
18#include <Poly.ixx>
19#include <gp_Pnt.hxx>
20#include <gp_Pnt2d.hxx>
21#include <Poly_Triangle.hxx>
22#include <TColgp_Array1OfPnt.hxx>
23#include <TColgp_Array1OfPnt.hxx>
24#include <TColStd_Array1OfReal.hxx>
25#include <Poly_Array1OfTriangle.hxx>
26#include <Poly_ListOfTriangulation.hxx>
27
28#include <Poly_Polygon3D.hxx>
29#include <Poly_Polygon2D.hxx>
30#include <Precision.hxx>
31#include <TShort_Array1OfShortReal.hxx>
32#include <TShort_HArray1OfShortReal.hxx>
33
34//=======================================================================
35//function : Catenate
36//purpose : Join several triangulations to one new triangulation object
37//=======================================================================
38
4952a30a 39Handle(Poly_Triangulation) Poly::Catenate (const Poly_ListOfTriangulation& lstTri)
7fd59977 40{
41 Standard_Integer nNodes(0);
42 Standard_Integer nTrian(0);
43
44 // Sum up the total number of nodes.
45 Poly_ListOfTriangulation::Iterator anIter(lstTri);
46 for (; anIter.More(); anIter.Next()) {
47 const Handle(Poly_Triangulation)& aTri = anIter.Value();
48 if (aTri.IsNull() == Standard_False) {
49 nNodes += aTri->NbNodes();
50 nTrian += aTri->NbTriangles();
51 }
52 }
53
54 Handle(Poly_Triangulation) aResult;
55 if (nNodes > 0) {
56 aResult = new Poly_Triangulation(nNodes, nTrian, Standard_False);
57 Standard_Integer i, iNode[3];
58 nNodes = 0;
59 nTrian = 0;
7fd59977 60 for (anIter.Init(lstTri); anIter.More(); anIter.Next()) {
61 const Handle(Poly_Triangulation)& aTri = anIter.Value();
62 if (aTri.IsNull() == Standard_False) {
7fd59977 63 const Standard_Integer nbNodes = aTri->NbNodes();
64 const Standard_Integer nbTrian = aTri->NbTriangles();
65 for (i = 1; i <= nbNodes; i++) {
6c1f47fd 66 aResult->ChangeNode (i + nNodes) = aTri->Node (i);
7fd59977 67 }
68 for (i = 1; i <= nbTrian; i++) {
6c1f47fd 69 aTri->Triangle (i).Get(iNode[0], iNode[1], iNode[2]);
70 aResult->ChangeTriangle (i + nTrian) = Poly_Triangle(iNode[0] + nNodes,
7fd59977 71 iNode[1] + nNodes,
6c1f47fd 72 iNode[2] + nNodes);
7fd59977 73 }
74 nNodes += nbNodes;
75 nTrian += nbTrian;
76 }
77 }
78 }
79 return aResult;
80}
81
82//=======================================================================
83//function : Write
4952a30a 84//purpose :
7fd59977 85//=======================================================================
86
4952a30a 87void Poly::Write(const Handle(Poly_Triangulation)& T,
88 Standard_OStream& OS,
7fd59977 89 const Standard_Boolean Compact)
90{
91 OS << "Poly_Triangulation\n";
92 if (Compact) {
93 OS << T->NbNodes() << " " << T->NbTriangles() << " ";
94 OS << ((T->HasUVNodes()) ? "1" : "0") << "\n";
95 }
96 else {
97 OS << setw(8) << T->NbNodes() << " Nodes\n";
98 OS << setw(8) << T->NbTriangles() << " Triangles\n";
99 OS << ((T->HasUVNodes()) ? "with" : "without") << " UV nodes\n";
100 }
101
102 // write the deflection
103
104 if (!Compact) OS << "Deflection : ";
105 OS << T->Deflection() << "\n";
106
107 // write the 3d nodes
108
109 if (!Compact) OS << "\n3D Nodes :\n";
110
111 Standard_Integer i, nbNodes = T->NbNodes();
7fd59977 112 for (i = 1; i <= nbNodes; i++) {
113 if (!Compact) OS << setw(10) << i << " : ";
114 if (!Compact) OS << setw(17);
6c1f47fd 115 OS << T->Node (i).X() << " ";
7fd59977 116 if (!Compact) OS << setw(17);
6c1f47fd 117 OS << T->Node (i).Y() << " ";
7fd59977 118 if (!Compact) OS << setw(17);
6c1f47fd 119 OS << T->Node (i).Z() << "\n";
7fd59977 120 }
121
122 if (T->HasUVNodes()) {
123 if (!Compact) OS << "\nUV Nodes :\n";
7fd59977 124 for (i = 1; i <= nbNodes; i++) {
125 if (!Compact) OS << setw(10) << i << " : ";
126 if (!Compact) OS << setw(17);
6c1f47fd 127 OS << T->UVNode (i).X() << " ";
7fd59977 128 if (!Compact) OS << setw(17);
6c1f47fd 129 OS << T->UVNode (i).Y() << "\n";
7fd59977 130 }
131 }
4952a30a 132
7fd59977 133 if (!Compact) OS << "\nTriangles :\n";
134 Standard_Integer nbTriangles = T->NbTriangles();
135 Standard_Integer n1, n2, n3;
7fd59977 136 for (i = 1; i <= nbTriangles; i++) {
137 if (!Compact) OS << setw(10) << i << " : ";
6c1f47fd 138 T->Triangle(i).Get(n1, n2, n3);
7fd59977 139 if (!Compact) OS << setw(10);
140 OS << n1 << " ";
141 if (!Compact) OS << setw(10);
142 OS << n2 << " ";
143 if (!Compact) OS << setw(10);
144 OS << n3 << "\n";
145 }
146
147}
148
149//=======================================================================
150//function : Write
4952a30a 151//purpose :
7fd59977 152//=======================================================================
153
4952a30a 154void Poly::Write(const Handle(Poly_Polygon3D)& P,
155 Standard_OStream& OS,
7fd59977 156 const Standard_Boolean Compact)
157{
158 OS << "Poly_Polygon3D\n";
159 if (Compact) {
160 OS << P->NbNodes() << " ";
161 OS << ((P->HasParameters()) ? "1" : "0") << "\n";
162 }
163 else {
164 OS << setw(8) << P->NbNodes() << " Nodes\n";
165 OS << ((P->HasParameters()) ? "with" : "without") << " parameters\n";
166 }
167
168 // write the deflection
169
170 if (!Compact) OS << "Deflection : ";
171 OS << P->Deflection() << "\n";
172
173 // write the nodes
174
175 if (!Compact) OS << "\nNodes :\n";
176
177 Standard_Integer i, nbNodes = P->NbNodes();
178 const TColgp_Array1OfPnt& Nodes = P->Nodes();
179 for (i = 1; i <= nbNodes; i++) {
180 if (!Compact) OS << setw(10) << i << " : ";
181 if (!Compact) OS << setw(17);
182 OS << Nodes(i).X() << " ";
183 if (!Compact) OS << setw(17);
184 OS << Nodes(i).Y() << " ";
185 if (!Compact) OS << setw(17);
186 OS << Nodes(i).Z() << "\n";
187 }
188
189 if (P->HasParameters()) {
190 if (!Compact) OS << "\nParameters :\n";
191 const TColStd_Array1OfReal& Param = P->Parameters();
192 for (i = 1; i <= nbNodes; i++) {
193 OS << Param(i) << " ";
194 }
195 OS <<"\n";
196 }
197
198
199}
200
201
202//=======================================================================
203//function : Write
4952a30a 204//purpose :
7fd59977 205//=======================================================================
206
4952a30a 207void Poly::Write(const Handle(Poly_Polygon2D)& P,
208 Standard_OStream& OS,
7fd59977 209 const Standard_Boolean Compact)
210{
211 OS << "Poly_Polygon2D\n";
212 if (Compact) {
213 OS << P->NbNodes() << " ";
214 }
215 else {
216 OS << setw(8) << P->NbNodes() << " Nodes\n";
217 }
218
219 // write the deflection
220
221 if (!Compact) OS << "Deflection : ";
222 OS << P->Deflection() << "\n";
223
224 // write the nodes
225
226 if (!Compact) OS << "\nNodes :\n";
227
228 Standard_Integer i, nbNodes = P->NbNodes();
229 const TColgp_Array1OfPnt2d& Nodes = P->Nodes();
230 for (i = 1; i <= nbNodes; i++) {
231 if (!Compact) OS << setw(10) << i << " : ";
232 if (!Compact) OS << setw(17);
233 OS << Nodes(i).X() << " ";
234 if (!Compact) OS << setw(17);
235 OS << Nodes(i).Y() << "\n";
236 }
237}
238
239
240
241//=======================================================================
242//function : Dump
4952a30a 243//purpose :
7fd59977 244//=======================================================================
245
246void Poly::Dump(const Handle(Poly_Triangulation)& T, Standard_OStream& OS)
247{
248 Poly::Write(T,OS,Standard_False);
249}
250
251
252//=======================================================================
253//function : Dump
4952a30a 254//purpose :
7fd59977 255//=======================================================================
256
257void Poly::Dump(const Handle(Poly_Polygon3D)& P, Standard_OStream& OS)
258{
259 Poly::Write(P,OS,Standard_False);
260}
261
262
263//=======================================================================
264//function : Dump
4952a30a 265//purpose :
7fd59977 266//=======================================================================
267
268void Poly::Dump(const Handle(Poly_Polygon2D)& P, Standard_OStream& OS)
269{
270 Poly::Write(P,OS,Standard_False);
271}
272
273
274//=======================================================================
275//function : ReadTriangulation
4952a30a 276//purpose :
7fd59977 277//=======================================================================
278
279Handle(Poly_Triangulation) Poly::ReadTriangulation(Standard_IStream& IS)
280{
281 // Read a triangulation
4952a30a 282
7fd59977 283 char line[100];
284 IS >> line;
285 if (strcmp(line,"Poly_Triangulation")) {
0797d9d3 286#ifdef OCCT_DEBUG
7fd59977 287 cout << "Not a Triangulation in the file" << endl;
63c629aa 288#endif
7fd59977 289 return Handle(Poly_Triangulation)();
290 }
291
292 Standard_Integer nbNodes, nbTriangles;
293 Standard_Boolean hasUV;
294 IS >> nbNodes >> nbTriangles >> hasUV;
295
296 Standard_Real d;
297 IS >> d;
298
299 // read the 3d nodes
300 Standard_Real x,y,z;
301 Standard_Integer i;
302 TColgp_Array1OfPnt Nodes(1, nbNodes);
303 TColgp_Array1OfPnt2d UVNodes(1, nbNodes);
304
305 for (i = 1; i <= nbNodes; i++) {
306 IS >> x >> y >> z;
307 Nodes(i).SetCoord(x,y,z);
308 }
309
310 // read the UV points if necessary
311
312 if (hasUV) {
313 for (i = 1; i <= nbNodes; i++) {
314 IS >> x >> y;
315 UVNodes(i).SetCoord(x,y);
316 }
317 }
318
319
320 // read the triangles
321 Standard_Integer n1,n2,n3;
322 Poly_Array1OfTriangle Triangles(1, nbTriangles);
323 for (i = 1; i <= nbTriangles; i++) {
324 IS >> n1 >> n2 >> n3;
325 Triangles(i).Set(n1,n2,n3);
326 }
327
4952a30a 328
7fd59977 329 Handle(Poly_Triangulation) T;
330
331 if (hasUV) T = new Poly_Triangulation(Nodes,UVNodes,Triangles);
332 else T = new Poly_Triangulation(Nodes,Triangles);
333
334 T->Deflection(d);
335
336 return T;
337}
338
339
340//=======================================================================
341//function : ReadPolygon3D
4952a30a 342//purpose :
7fd59977 343//=======================================================================
344
345Handle(Poly_Polygon3D) Poly::ReadPolygon3D(Standard_IStream& IS)
346{
347 // Read a 3d polygon
4952a30a 348
7fd59977 349 char line[100];
350 IS >> line;
351 if (strcmp(line,"Poly_Polygon3D")) {
0797d9d3 352#ifdef OCCT_DEBUG
7fd59977 353 cout << "Not a Polygon3D in the file" << endl;
63c629aa 354#endif
7fd59977 355 return Handle(Poly_Polygon3D)();
356 }
357
358 Standard_Integer nbNodes;
359 IS >> nbNodes;
360
361 Standard_Boolean hasparameters;
362 IS >> hasparameters;
363
364 Standard_Real d;
365 IS >> d;
366
367 // read the nodes
368 Standard_Real x,y,z;
369 Standard_Integer i;
370 TColgp_Array1OfPnt Nodes(1, nbNodes);
371
372 for (i = 1; i <= nbNodes; i++) {
373 IS >> x >> y >> z;
374 Nodes(i).SetCoord(x,y,z);
375 }
376
377 TColStd_Array1OfReal Param(1,nbNodes);
378 if (hasparameters) {
379 for (i = 1; i <= nbNodes; i++) {
380 IS >> Param(i);
381 }
382 }
383
384 Handle(Poly_Polygon3D) P;
385 if (!hasparameters)
386 P = new Poly_Polygon3D(Nodes);
4952a30a 387 else
7fd59977 388 P = new Poly_Polygon3D(Nodes, Param);
389
390 P->Deflection(d);
391
392 return P;
393}
394
395//=======================================================================
396//function : ReadPolygon3D
4952a30a 397//purpose :
7fd59977 398//=======================================================================
399
400Handle(Poly_Polygon2D) Poly::ReadPolygon2D(Standard_IStream& IS)
401{
402 // Read a 2d polygon
4952a30a 403
7fd59977 404 char line[100];
405 IS >> line;
406 if (strcmp(line,"Poly_Polygon2D")) {
0797d9d3 407#ifdef OCCT_DEBUG
7fd59977 408 cout << "Not a Polygon2D in the file" << endl;
63c629aa 409#endif
7fd59977 410 return Handle(Poly_Polygon2D)();
411 }
412
413 Standard_Integer nbNodes;
414 IS >> nbNodes;
415
416 Standard_Real d;
417 IS >> d;
418
419 // read the nodes
420 Standard_Real x,y;
421 Standard_Integer i;
422 TColgp_Array1OfPnt2d Nodes(1, nbNodes);
423
424 for (i = 1; i <= nbNodes; i++) {
425 IS >> x >> y;
426 Nodes(i).SetCoord(x,y);
427 }
428
4952a30a 429 Handle(Poly_Polygon2D) P =
7fd59977 430 new Poly_Polygon2D(Nodes);
4952a30a 431
7fd59977 432 P->Deflection(d);
433
434 return P;
435}
436
437//=======================================================================
438//function : ComputeNormals
4952a30a 439//purpose :
7fd59977 440//=======================================================================
441
442void Poly::ComputeNormals(const Handle(Poly_Triangulation)& Tri)
443{
4952a30a 444 Standard_Integer nbNormVal = Tri->NbNodes() * 3;
7fd59977 445 const Handle(TShort_HArray1OfShortReal) Normals =
446 new TShort_HArray1OfShortReal(1, nbNormVal);
447 Normals->Init(0.F);
448
449 Standard_ShortReal * arrNormal = &(Normals->ChangeValue(1));
450
451 Standard_Real aCoord[3];
452 Standard_Integer iNode[3] = {0, 0, 0};
453 Standard_Integer iN, iTri;
08cd2f6b 454 const Standard_Real eps2 = Precision::SquareConfusion();
7fd59977 455
6c1f47fd 456 for (iTri = 1; iTri <= Tri->NbTriangles(); iTri++) {
7fd59977 457 // Get the nodes of the current triangle
6c1f47fd 458 Tri->Triangle (iTri).Get (iNode[0], iNode[1], iNode[2]);
7fd59977 459 const gp_XYZ aVec[2] = {
6c1f47fd 460 Tri->Node (iNode[1]).XYZ() - Tri->Node (iNode[0]).XYZ(),
461 Tri->Node (iNode[2]).XYZ() - Tri->Node (iNode[0]).XYZ()
7fd59977 462 };
463
464 // Find the normal vector of the current triangle
465 gp_XYZ aNorm = aVec[0] ^ aVec[1];
466 const Standard_Real aMod = aNorm.SquareModulus();
467 if (aMod > eps2) {
468 aNorm /= sqrt(aMod);
469 aNorm.Coord (aCoord[0], aCoord[1], aCoord[2]);
470 iNode[0] = (iNode[0]-1)*3;
471 iNode[1] = (iNode[1]-1)*3;
472 iNode[2] = (iNode[2]-1)*3;
473 arrNormal[iNode[0]+0] += (Standard_ShortReal)aCoord[0];
474 arrNormal[iNode[0]+1] += (Standard_ShortReal)aCoord[1];
475 arrNormal[iNode[0]+2] += (Standard_ShortReal)aCoord[2];
476 arrNormal[iNode[1]+0] += (Standard_ShortReal)aCoord[0];
477 arrNormal[iNode[1]+1] += (Standard_ShortReal)aCoord[1];
478 arrNormal[iNode[1]+2] += (Standard_ShortReal)aCoord[2];
479 arrNormal[iNode[2]+0] += (Standard_ShortReal)aCoord[0];
480 arrNormal[iNode[2]+1] += (Standard_ShortReal)aCoord[1];
481 arrNormal[iNode[2]+2] += (Standard_ShortReal)aCoord[2];
482 }
483 }
484 // Normalize all vectors
485 for (iN = 0; iN < nbNormVal; iN+=3) {
486 Standard_Real aMod (arrNormal[iN+0]*arrNormal[iN+0] +
487 arrNormal[iN+1]*arrNormal[iN+1] +
488 arrNormal[iN+2]*arrNormal[iN+2]);
489 if (aMod < eps2) {
490 arrNormal[iN+0] = 0.f;
491 arrNormal[iN+1] = 0.f;
492 arrNormal[iN+2] = 1.f;
493 } else {
494 aMod = sqrt(aMod);
495 arrNormal[iN+0] = Standard_ShortReal(arrNormal[iN+0]/aMod);
496 arrNormal[iN+1] = Standard_ShortReal(arrNormal[iN+1]/aMod);
497 arrNormal[iN+2] = Standard_ShortReal(arrNormal[iN+2]/aMod);
498 }
499 }
500
501 Tri->SetNormals(Normals);
502}
4952a30a 503
504//=======================================================================
505//function : PointOnTriangle
506//purpose :
507//=======================================================================
508
509Standard_Real Poly::PointOnTriangle (const gp_XY& theP1, const gp_XY& theP2, const gp_XY& theP3,
510 const gp_XY& theP, gp_XY& theUV)
511{
512 gp_XY aDP = theP - theP1;
513 gp_XY aDU = theP2 - theP1;
514 gp_XY aDV = theP3 - theP1;
515 Standard_Real aDet = aDU ^ aDV;
516
517 // case of non-degenerated triangle
518 if ( Abs (aDet) > gp::Resolution() )
519 {
520 Standard_Real aU = (aDP ^ aDV) / aDet;
521 Standard_Real aV = -(aDP ^ aDU) / aDet;
522
523 // if point is inside triangle, just return parameters
524 if ( aU > -gp::Resolution() &&
525 aV > -gp::Resolution() &&
526 1. - aU - aV > -gp::Resolution() )
527 {
528 theUV.SetCoord (aU, aV);
529 return 0.;
530 }
531
532 // else find closest point on triangle sides; note that in general case
533 // triangle can be very distorted and it is necessary to check
534 // projection on all sides regardless of values of computed parameters
535
536 // project on side U=0
537 aU = 0.;
538 aV = Min (1., Max (0., (aDP * aDV) / aDV.SquareModulus()));
539 Standard_Real aD = (aV * aDV - aDP).SquareModulus();
540
541 // project on side V=0
542 Standard_Real u = Min (1., Max (0., (aDP * aDU) / aDU.SquareModulus()));
543 Standard_Real d = (u * aDU - aDP).SquareModulus();
544 if ( d < aD )
545 {
546 aU = u;
547 aV = 0.;
548 aD = d;
549 }
550
551 // project on side U+V=1
552 gp_XY aDUV = aDV - aDU;
553 Standard_Real v = Min (1., Max (0., ((aDP - aDU) * aDUV) / aDUV.SquareModulus()));
554 d = (theP2 + v * aDUV - theP).SquareModulus();
555 if ( d < aD )
556 {
557 aU = 1. - v;
558 aV = v;
559 aD = d;
560 }
561
562 theUV.SetCoord (aU, aV);
563 return aD;
564 }
565
566 // degenerated triangle
567 Standard_Real aL2U = aDU.SquareModulus();
568 Standard_Real aL2V = aDV.SquareModulus();
569 if ( aL2U < gp::Resolution() ) // side 1-2 is degenerated
570 {
571 if ( aL2V < gp::Resolution() ) // whole triangle is degenerated to point
572 {
573 theUV.SetCoord (0., 0.);
574 return (theP - theP1).SquareModulus();
575 }
576 else
577 {
578 theUV.SetCoord (0., (aDP * aDV) / aL2V);
579 return (theP - (theP1 + theUV.Y() * aDV)).SquareModulus();
580 }
581 }
582 else if ( aL2V < gp::Resolution() ) // side 1-3 is degenerated
583 {
584 theUV.SetCoord ((aDP * aDU) / aL2U, 0.);
585 return (theP - (theP1 + theUV.X() * aDU)).SquareModulus();
586 }
587 else // sides 1-2 and 1-3 are collinear
588 {
589 // select parameter on one of sides so as to have points closer to picked
590 Standard_Real aU = Min (1., Max (0., (aDP * aDU) / aL2U));
591 Standard_Real aV = Min (1., Max (0., (aDP * aDV) / aL2V));
592 Standard_Real aD1 = (aDP - aU * aDU).SquareModulus();
593 Standard_Real aD2 = (aDP - aV * aDV).SquareModulus();
594 if ( aD1 < aD2 )
595 {
596 theUV.SetCoord ((aDP * aDU) / aL2U, 0.);
597 return aD1;
598 }
599 else
600 {
601 theUV.SetCoord (0., (aDP * aDV) / aL2V);
602 return aD2;
603 }
604 }
605}
606