0031687: Draw Harness, ViewerTest - extend command vrenderparams with option updating...
[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
42cf5bc1 17
7fd59977 18#include <gp_Pnt.hxx>
19#include <gp_Pnt2d.hxx>
42cf5bc1 20#include <gp_XY.hxx>
21#include <Poly.hxx>
7fd59977 22#include <Poly_Array1OfTriangle.hxx>
23#include <Poly_ListOfTriangulation.hxx>
7fd59977 24#include <Poly_Polygon2D.hxx>
42cf5bc1 25#include <Poly_Polygon3D.hxx>
26#include <Poly_Triangle.hxx>
27#include <Poly_Triangulation.hxx>
7fd59977 28#include <Precision.hxx>
42cf5bc1 29#include <Standard_Stream.hxx>
30#include <TColgp_Array1OfPnt.hxx>
31#include <TColStd_Array1OfReal.hxx>
7fd59977 32#include <TShort_Array1OfShortReal.hxx>
33#include <TShort_HArray1OfShortReal.hxx>
34
35//=======================================================================
36//function : Catenate
37//purpose : Join several triangulations to one new triangulation object
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;
60 TColgp_Array1OfPnt& arrNode = aResult->ChangeNodes();
61 Poly_Array1OfTriangle& arrTrian = aResult->ChangeTriangles();
62 for (anIter.Init(lstTri); anIter.More(); anIter.Next()) {
63 const Handle(Poly_Triangulation)& aTri = anIter.Value();
64 if (aTri.IsNull() == Standard_False) {
65 const TColgp_Array1OfPnt& srcNode = aTri->Nodes();
66 const Poly_Array1OfTriangle& srcTrian = aTri->Triangles();
67 const Standard_Integer nbNodes = aTri->NbNodes();
68 const Standard_Integer nbTrian = aTri->NbTriangles();
69 for (i = 1; i <= nbNodes; i++) {
70 arrNode.SetValue(i + nNodes, srcNode(i));
71 }
72 for (i = 1; i <= nbTrian; i++) {
73 srcTrian(i).Get(iNode[0], iNode[1], iNode[2]);
74 arrTrian.SetValue(i + nTrian, Poly_Triangle(iNode[0] + nNodes,
75 iNode[1] + nNodes,
76 iNode[2] + nNodes));
77 }
78 nNodes += nbNodes;
79 nTrian += nbTrian;
80 }
81 }
82 }
83 return aResult;
84}
85
86//=======================================================================
87//function : Write
4952a30a 88//purpose :
7fd59977 89//=======================================================================
90
4952a30a 91void Poly::Write(const Handle(Poly_Triangulation)& T,
92 Standard_OStream& OS,
7fd59977 93 const Standard_Boolean Compact)
94{
95 OS << "Poly_Triangulation\n";
96 if (Compact) {
97 OS << T->NbNodes() << " " << T->NbTriangles() << " ";
98 OS << ((T->HasUVNodes()) ? "1" : "0") << "\n";
99 }
100 else {
04232180 101 OS << std::setw(8) << T->NbNodes() << " Nodes\n";
102 OS << std::setw(8) << T->NbTriangles() << " Triangles\n";
7fd59977 103 OS << ((T->HasUVNodes()) ? "with" : "without") << " UV nodes\n";
104 }
105
106 // write the deflection
107
108 if (!Compact) OS << "Deflection : ";
109 OS << T->Deflection() << "\n";
110
111 // write the 3d nodes
112
113 if (!Compact) OS << "\n3D Nodes :\n";
114
115 Standard_Integer i, nbNodes = T->NbNodes();
116 const TColgp_Array1OfPnt& Nodes = T->Nodes();
117 for (i = 1; i <= nbNodes; i++) {
04232180 118 if (!Compact) OS << std::setw(10) << i << " : ";
119 if (!Compact) OS << std::setw(17);
7fd59977 120 OS << Nodes(i).X() << " ";
04232180 121 if (!Compact) OS << std::setw(17);
7fd59977 122 OS << Nodes(i).Y() << " ";
04232180 123 if (!Compact) OS << std::setw(17);
7fd59977 124 OS << Nodes(i).Z() << "\n";
125 }
126
127 if (T->HasUVNodes()) {
128 if (!Compact) OS << "\nUV Nodes :\n";
129 const TColgp_Array1OfPnt2d& UVNodes = T->UVNodes();
130 for (i = 1; i <= nbNodes; i++) {
04232180 131 if (!Compact) OS << std::setw(10) << i << " : ";
132 if (!Compact) OS << std::setw(17);
7fd59977 133 OS << UVNodes(i).X() << " ";
04232180 134 if (!Compact) OS << std::setw(17);
7fd59977 135 OS << UVNodes(i).Y() << "\n";
136 }
137 }
4952a30a 138
7fd59977 139 if (!Compact) OS << "\nTriangles :\n";
140 Standard_Integer nbTriangles = T->NbTriangles();
141 Standard_Integer n1, n2, n3;
142 const Poly_Array1OfTriangle& Triangles = T->Triangles();
143 for (i = 1; i <= nbTriangles; i++) {
04232180 144 if (!Compact) OS << std::setw(10) << i << " : ";
7fd59977 145 Triangles(i).Get(n1, n2, n3);
04232180 146 if (!Compact) OS << std::setw(10);
7fd59977 147 OS << n1 << " ";
04232180 148 if (!Compact) OS << std::setw(10);
7fd59977 149 OS << n2 << " ";
04232180 150 if (!Compact) OS << std::setw(10);
7fd59977 151 OS << n3 << "\n";
152 }
153
154}
155
156//=======================================================================
157//function : Write
4952a30a 158//purpose :
7fd59977 159//=======================================================================
160
4952a30a 161void Poly::Write(const Handle(Poly_Polygon3D)& P,
162 Standard_OStream& OS,
7fd59977 163 const Standard_Boolean Compact)
164{
165 OS << "Poly_Polygon3D\n";
166 if (Compact) {
167 OS << P->NbNodes() << " ";
168 OS << ((P->HasParameters()) ? "1" : "0") << "\n";
169 }
170 else {
04232180 171 OS << std::setw(8) << P->NbNodes() << " Nodes\n";
7fd59977 172 OS << ((P->HasParameters()) ? "with" : "without") << " parameters\n";
173 }
174
175 // write the deflection
176
177 if (!Compact) OS << "Deflection : ";
178 OS << P->Deflection() << "\n";
179
180 // write the nodes
181
182 if (!Compact) OS << "\nNodes :\n";
183
184 Standard_Integer i, nbNodes = P->NbNodes();
185 const TColgp_Array1OfPnt& Nodes = P->Nodes();
186 for (i = 1; i <= nbNodes; i++) {
04232180 187 if (!Compact) OS << std::setw(10) << i << " : ";
188 if (!Compact) OS << std::setw(17);
7fd59977 189 OS << Nodes(i).X() << " ";
04232180 190 if (!Compact) OS << std::setw(17);
7fd59977 191 OS << Nodes(i).Y() << " ";
04232180 192 if (!Compact) OS << std::setw(17);
7fd59977 193 OS << Nodes(i).Z() << "\n";
194 }
195
196 if (P->HasParameters()) {
197 if (!Compact) OS << "\nParameters :\n";
198 const TColStd_Array1OfReal& Param = P->Parameters();
199 for (i = 1; i <= nbNodes; i++) {
200 OS << Param(i) << " ";
201 }
202 OS <<"\n";
203 }
204
205
206}
207
208
209//=======================================================================
210//function : Write
4952a30a 211//purpose :
7fd59977 212//=======================================================================
213
4952a30a 214void Poly::Write(const Handle(Poly_Polygon2D)& P,
215 Standard_OStream& OS,
7fd59977 216 const Standard_Boolean Compact)
217{
218 OS << "Poly_Polygon2D\n";
219 if (Compact) {
220 OS << P->NbNodes() << " ";
221 }
222 else {
04232180 223 OS << std::setw(8) << P->NbNodes() << " Nodes\n";
7fd59977 224 }
225
226 // write the deflection
227
228 if (!Compact) OS << "Deflection : ";
229 OS << P->Deflection() << "\n";
230
231 // write the nodes
232
233 if (!Compact) OS << "\nNodes :\n";
234
235 Standard_Integer i, nbNodes = P->NbNodes();
236 const TColgp_Array1OfPnt2d& Nodes = P->Nodes();
237 for (i = 1; i <= nbNodes; i++) {
04232180 238 if (!Compact) OS << std::setw(10) << i << " : ";
239 if (!Compact) OS << std::setw(17);
7fd59977 240 OS << Nodes(i).X() << " ";
04232180 241 if (!Compact) OS << std::setw(17);
7fd59977 242 OS << Nodes(i).Y() << "\n";
243 }
244}
245
246
247
248//=======================================================================
249//function : Dump
4952a30a 250//purpose :
7fd59977 251//=======================================================================
252
253void Poly::Dump(const Handle(Poly_Triangulation)& T, Standard_OStream& OS)
254{
255 Poly::Write(T,OS,Standard_False);
256}
257
258
259//=======================================================================
260//function : Dump
4952a30a 261//purpose :
7fd59977 262//=======================================================================
263
264void Poly::Dump(const Handle(Poly_Polygon3D)& P, Standard_OStream& OS)
265{
266 Poly::Write(P,OS,Standard_False);
267}
268
269
270//=======================================================================
271//function : Dump
4952a30a 272//purpose :
7fd59977 273//=======================================================================
274
275void Poly::Dump(const Handle(Poly_Polygon2D)& P, Standard_OStream& OS)
276{
277 Poly::Write(P,OS,Standard_False);
278}
279
280
281//=======================================================================
282//function : ReadTriangulation
4952a30a 283//purpose :
7fd59977 284//=======================================================================
285
286Handle(Poly_Triangulation) Poly::ReadTriangulation(Standard_IStream& IS)
287{
288 // Read a triangulation
4952a30a 289
7fd59977 290 char line[100];
291 IS >> line;
292 if (strcmp(line,"Poly_Triangulation")) {
0797d9d3 293#ifdef OCCT_DEBUG
04232180 294 std::cout << "Not a Triangulation in the file" << std::endl;
63c629aa 295#endif
7fd59977 296 return Handle(Poly_Triangulation)();
297 }
298
299 Standard_Integer nbNodes, nbTriangles;
300 Standard_Boolean hasUV;
301 IS >> nbNodes >> nbTriangles >> hasUV;
302
303 Standard_Real d;
304 IS >> d;
305
306 // read the 3d nodes
307 Standard_Real x,y,z;
308 Standard_Integer i;
309 TColgp_Array1OfPnt Nodes(1, nbNodes);
310 TColgp_Array1OfPnt2d UVNodes(1, nbNodes);
311
312 for (i = 1; i <= nbNodes; i++) {
313 IS >> x >> y >> z;
314 Nodes(i).SetCoord(x,y,z);
315 }
316
317 // read the UV points if necessary
318
319 if (hasUV) {
320 for (i = 1; i <= nbNodes; i++) {
321 IS >> x >> y;
322 UVNodes(i).SetCoord(x,y);
323 }
324 }
325
326
327 // read the triangles
328 Standard_Integer n1,n2,n3;
329 Poly_Array1OfTriangle Triangles(1, nbTriangles);
330 for (i = 1; i <= nbTriangles; i++) {
331 IS >> n1 >> n2 >> n3;
332 Triangles(i).Set(n1,n2,n3);
333 }
334
4952a30a 335
7fd59977 336 Handle(Poly_Triangulation) T;
337
338 if (hasUV) T = new Poly_Triangulation(Nodes,UVNodes,Triangles);
339 else T = new Poly_Triangulation(Nodes,Triangles);
340
341 T->Deflection(d);
342
343 return T;
344}
345
346
347//=======================================================================
348//function : ReadPolygon3D
4952a30a 349//purpose :
7fd59977 350//=======================================================================
351
352Handle(Poly_Polygon3D) Poly::ReadPolygon3D(Standard_IStream& IS)
353{
354 // Read a 3d polygon
4952a30a 355
7fd59977 356 char line[100];
357 IS >> line;
358 if (strcmp(line,"Poly_Polygon3D")) {
0797d9d3 359#ifdef OCCT_DEBUG
04232180 360 std::cout << "Not a Polygon3D in the file" << std::endl;
63c629aa 361#endif
7fd59977 362 return Handle(Poly_Polygon3D)();
363 }
364
365 Standard_Integer nbNodes;
366 IS >> nbNodes;
367
368 Standard_Boolean hasparameters;
369 IS >> hasparameters;
370
371 Standard_Real d;
372 IS >> d;
373
374 // read the nodes
375 Standard_Real x,y,z;
376 Standard_Integer i;
377 TColgp_Array1OfPnt Nodes(1, nbNodes);
378
379 for (i = 1; i <= nbNodes; i++) {
380 IS >> x >> y >> z;
381 Nodes(i).SetCoord(x,y,z);
382 }
383
384 TColStd_Array1OfReal Param(1,nbNodes);
385 if (hasparameters) {
386 for (i = 1; i <= nbNodes; i++) {
387 IS >> Param(i);
388 }
389 }
390
391 Handle(Poly_Polygon3D) P;
392 if (!hasparameters)
393 P = new Poly_Polygon3D(Nodes);
4952a30a 394 else
7fd59977 395 P = new Poly_Polygon3D(Nodes, Param);
396
397 P->Deflection(d);
398
399 return P;
400}
401
402//=======================================================================
403//function : ReadPolygon3D
4952a30a 404//purpose :
7fd59977 405//=======================================================================
406
407Handle(Poly_Polygon2D) Poly::ReadPolygon2D(Standard_IStream& IS)
408{
409 // Read a 2d polygon
4952a30a 410
7fd59977 411 char line[100];
412 IS >> line;
413 if (strcmp(line,"Poly_Polygon2D")) {
0797d9d3 414#ifdef OCCT_DEBUG
04232180 415 std::cout << "Not a Polygon2D in the file" << std::endl;
63c629aa 416#endif
7fd59977 417 return Handle(Poly_Polygon2D)();
418 }
419
420 Standard_Integer nbNodes;
421 IS >> nbNodes;
422
423 Standard_Real d;
424 IS >> d;
425
426 // read the nodes
427 Standard_Real x,y;
428 Standard_Integer i;
429 TColgp_Array1OfPnt2d Nodes(1, nbNodes);
430
431 for (i = 1; i <= nbNodes; i++) {
432 IS >> x >> y;
433 Nodes(i).SetCoord(x,y);
434 }
435
4952a30a 436 Handle(Poly_Polygon2D) P =
7fd59977 437 new Poly_Polygon2D(Nodes);
4952a30a 438
7fd59977 439 P->Deflection(d);
440
441 return P;
442}
443
444//=======================================================================
445//function : ComputeNormals
4952a30a 446//purpose :
7fd59977 447//=======================================================================
dc2cc135 448void Poly::ComputeNormals (const Handle(Poly_Triangulation)& theTri)
7fd59977 449{
dc2cc135 450 const TColgp_Array1OfPnt& aNodes = theTri->Nodes();
451 const Standard_Integer aNbNodes = aNodes.Size();
452
453 const Handle(TShort_HArray1OfShortReal) aNormals = new TShort_HArray1OfShortReal (1, aNbNodes * 3);
454 aNormals->Init (0.0f);
455 Standard_ShortReal* aNormArr = &aNormals->ChangeFirst();
456
457 Standard_Integer anElem[3] = {0, 0, 0};
458 const Standard_Real anEps2 = gp::Resolution();
459 for (Poly_Array1OfTriangle::Iterator aTriIter (theTri->Triangles()); aTriIter.More(); aTriIter.Next())
460 {
461 aTriIter.Value().Get (anElem[0], anElem[1], anElem[2]);
462 const gp_Pnt& aNode0 = aNodes.Value (anElem[0]);
463 const gp_Pnt& aNode1 = aNodes.Value (anElem[1]);
464 const gp_Pnt& aNode2 = aNodes.Value (anElem[2]);
465
466 const gp_XYZ aVec01 = aNode1.XYZ() - aNode0.XYZ();
467 const gp_XYZ aVec02 = aNode2.XYZ() - aNode0.XYZ();
468 gp_XYZ aTriNorm = aVec01 ^ aVec02;
469 /*if (theToIgnoreTriangleSize)
470 {
471 const Standard_Real aMod = aTriNorm.SquareModulus();
472 if (aMod > anEps2)
473 {
474 aTriNorm /= Sqrt (aMod);
475 }
476 else
477 {
478 continue;
479 }
480 }*/
481
482 for (Standard_Integer aNodeIter = 0; aNodeIter < 3; ++aNodeIter)
483 {
484 const Standard_Size anIndex = (anElem[aNodeIter] - 1) * 3;
485 aNormArr[anIndex + 0] += Standard_ShortReal(aTriNorm.X());
486 aNormArr[anIndex + 1] += Standard_ShortReal(aTriNorm.Y());
487 aNormArr[anIndex + 2] += Standard_ShortReal(aTriNorm.Z());
7fd59977 488 }
489 }
dc2cc135 490
7fd59977 491 // Normalize all vectors
dc2cc135 492 gp_XYZ aNormXYZ;
493 for (Standard_Integer aNodeIter = 0; aNodeIter < aNbNodes; ++aNodeIter)
494 {
495 const Standard_Size anIndex = aNodeIter * 3;
496 aNormXYZ.SetCoord (aNormArr[anIndex + 0], aNormArr[anIndex + 1], aNormArr[anIndex + 2]);
497 const Standard_Real aMod2 = aNormXYZ.SquareModulus();
498 if (aMod2 < anEps2)
499 {
500 aNormArr[anIndex + 0] = 0.0f;
501 aNormArr[anIndex + 1] = 0.0f;
502 aNormArr[anIndex + 2] = 1.0f;
503 }
504 else
505 {
506 aNormXYZ /= Sqrt (aMod2);
507 aNormArr[anIndex + 0] = Standard_ShortReal(aNormXYZ.X());
508 aNormArr[anIndex + 1] = Standard_ShortReal(aNormXYZ.Y());
509 aNormArr[anIndex + 2] = Standard_ShortReal(aNormXYZ.Z());
7fd59977 510 }
511 }
512
dc2cc135 513 theTri->SetNormals (aNormals);
7fd59977 514}
4952a30a 515
516//=======================================================================
517//function : PointOnTriangle
518//purpose :
519//=======================================================================
520
521Standard_Real Poly::PointOnTriangle (const gp_XY& theP1, const gp_XY& theP2, const gp_XY& theP3,
522 const gp_XY& theP, gp_XY& theUV)
523{
524 gp_XY aDP = theP - theP1;
525 gp_XY aDU = theP2 - theP1;
526 gp_XY aDV = theP3 - theP1;
527 Standard_Real aDet = aDU ^ aDV;
528
529 // case of non-degenerated triangle
530 if ( Abs (aDet) > gp::Resolution() )
531 {
532 Standard_Real aU = (aDP ^ aDV) / aDet;
533 Standard_Real aV = -(aDP ^ aDU) / aDet;
534
535 // if point is inside triangle, just return parameters
536 if ( aU > -gp::Resolution() &&
537 aV > -gp::Resolution() &&
538 1. - aU - aV > -gp::Resolution() )
539 {
540 theUV.SetCoord (aU, aV);
541 return 0.;
542 }
543
544 // else find closest point on triangle sides; note that in general case
545 // triangle can be very distorted and it is necessary to check
546 // projection on all sides regardless of values of computed parameters
547
548 // project on side U=0
549 aU = 0.;
550 aV = Min (1., Max (0., (aDP * aDV) / aDV.SquareModulus()));
551 Standard_Real aD = (aV * aDV - aDP).SquareModulus();
552
553 // project on side V=0
554 Standard_Real u = Min (1., Max (0., (aDP * aDU) / aDU.SquareModulus()));
555 Standard_Real d = (u * aDU - aDP).SquareModulus();
556 if ( d < aD )
557 {
558 aU = u;
559 aV = 0.;
560 aD = d;
561 }
562
563 // project on side U+V=1
564 gp_XY aDUV = aDV - aDU;
565 Standard_Real v = Min (1., Max (0., ((aDP - aDU) * aDUV) / aDUV.SquareModulus()));
566 d = (theP2 + v * aDUV - theP).SquareModulus();
567 if ( d < aD )
568 {
569 aU = 1. - v;
570 aV = v;
571 aD = d;
572 }
573
574 theUV.SetCoord (aU, aV);
575 return aD;
576 }
577
578 // degenerated triangle
579 Standard_Real aL2U = aDU.SquareModulus();
580 Standard_Real aL2V = aDV.SquareModulus();
581 if ( aL2U < gp::Resolution() ) // side 1-2 is degenerated
582 {
583 if ( aL2V < gp::Resolution() ) // whole triangle is degenerated to point
584 {
585 theUV.SetCoord (0., 0.);
586 return (theP - theP1).SquareModulus();
587 }
588 else
589 {
590 theUV.SetCoord (0., (aDP * aDV) / aL2V);
591 return (theP - (theP1 + theUV.Y() * aDV)).SquareModulus();
592 }
593 }
594 else if ( aL2V < gp::Resolution() ) // side 1-3 is degenerated
595 {
596 theUV.SetCoord ((aDP * aDU) / aL2U, 0.);
597 return (theP - (theP1 + theUV.X() * aDU)).SquareModulus();
598 }
599 else // sides 1-2 and 1-3 are collinear
600 {
601 // select parameter on one of sides so as to have points closer to picked
602 Standard_Real aU = Min (1., Max (0., (aDP * aDU) / aL2U));
603 Standard_Real aV = Min (1., Max (0., (aDP * aDV) / aL2V));
604 Standard_Real aD1 = (aDP - aU * aDU).SquareModulus();
605 Standard_Real aD2 = (aDP - aV * aDV).SquareModulus();
606 if ( aD1 < aD2 )
607 {
608 theUV.SetCoord ((aDP * aDU) / aL2U, 0.);
609 return aD1;
610 }
611 else
612 {
613 theUV.SetCoord (0., (aDP * aDV) / aL2V);
614 return aD2;
615 }
616 }
617}
618