1 // Created on: 1995-03-06
2 // Created by: Laurent PAINNOT
3 // Copyright (c) 1995-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
6 // This file is part of Open CASCADE Technology software library.
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
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.
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
19 #include <gp_Pnt2d.hxx>
22 #include <Poly_Array1OfTriangle.hxx>
23 #include <Poly_ListOfTriangulation.hxx>
24 #include <Poly_Polygon2D.hxx>
25 #include <Poly_Polygon3D.hxx>
26 #include <Poly_Triangle.hxx>
27 #include <Poly_Triangulation.hxx>
28 #include <Precision.hxx>
29 #include <Standard_Stream.hxx>
30 #include <TColgp_Array1OfPnt.hxx>
31 #include <TColStd_Array1OfReal.hxx>
32 #include <TShort_Array1OfShortReal.hxx>
33 #include <TShort_HArray1OfShortReal.hxx>
35 //=======================================================================
37 //purpose : Join several triangulations to one new triangulation object
38 //=======================================================================
39 Handle(Poly_Triangulation) Poly::Catenate (const Poly_ListOfTriangulation& lstTri)
41 Standard_Integer nNodes(0);
42 Standard_Integer nTrian(0);
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();
54 Handle(Poly_Triangulation) aResult;
56 aResult = new Poly_Triangulation(nNodes, nTrian, Standard_False);
57 Standard_Integer i, iNode[3];
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));
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,
86 //=======================================================================
89 //=======================================================================
91 void Poly::Write(const Handle(Poly_Triangulation)& T,
93 const Standard_Boolean Compact)
95 OS << "Poly_Triangulation\n";
97 OS << T->NbNodes() << " " << T->NbTriangles() << " ";
98 OS << ((T->HasUVNodes()) ? "1" : "0") << "\n";
101 OS << setw(8) << T->NbNodes() << " Nodes\n";
102 OS << setw(8) << T->NbTriangles() << " Triangles\n";
103 OS << ((T->HasUVNodes()) ? "with" : "without") << " UV nodes\n";
106 // write the deflection
108 if (!Compact) OS << "Deflection : ";
109 OS << T->Deflection() << "\n";
111 // write the 3d nodes
113 if (!Compact) OS << "\n3D Nodes :\n";
115 Standard_Integer i, nbNodes = T->NbNodes();
116 const TColgp_Array1OfPnt& Nodes = T->Nodes();
117 for (i = 1; i <= nbNodes; i++) {
118 if (!Compact) OS << setw(10) << i << " : ";
119 if (!Compact) OS << setw(17);
120 OS << Nodes(i).X() << " ";
121 if (!Compact) OS << setw(17);
122 OS << Nodes(i).Y() << " ";
123 if (!Compact) OS << setw(17);
124 OS << Nodes(i).Z() << "\n";
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++) {
131 if (!Compact) OS << setw(10) << i << " : ";
132 if (!Compact) OS << setw(17);
133 OS << UVNodes(i).X() << " ";
134 if (!Compact) OS << setw(17);
135 OS << UVNodes(i).Y() << "\n";
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++) {
144 if (!Compact) OS << setw(10) << i << " : ";
145 Triangles(i).Get(n1, n2, n3);
146 if (!Compact) OS << setw(10);
148 if (!Compact) OS << setw(10);
150 if (!Compact) OS << setw(10);
156 //=======================================================================
159 //=======================================================================
161 void Poly::Write(const Handle(Poly_Polygon3D)& P,
162 Standard_OStream& OS,
163 const Standard_Boolean Compact)
165 OS << "Poly_Polygon3D\n";
167 OS << P->NbNodes() << " ";
168 OS << ((P->HasParameters()) ? "1" : "0") << "\n";
171 OS << setw(8) << P->NbNodes() << " Nodes\n";
172 OS << ((P->HasParameters()) ? "with" : "without") << " parameters\n";
175 // write the deflection
177 if (!Compact) OS << "Deflection : ";
178 OS << P->Deflection() << "\n";
182 if (!Compact) OS << "\nNodes :\n";
184 Standard_Integer i, nbNodes = P->NbNodes();
185 const TColgp_Array1OfPnt& Nodes = P->Nodes();
186 for (i = 1; i <= nbNodes; i++) {
187 if (!Compact) OS << setw(10) << i << " : ";
188 if (!Compact) OS << setw(17);
189 OS << Nodes(i).X() << " ";
190 if (!Compact) OS << setw(17);
191 OS << Nodes(i).Y() << " ";
192 if (!Compact) OS << setw(17);
193 OS << Nodes(i).Z() << "\n";
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) << " ";
209 //=======================================================================
212 //=======================================================================
214 void Poly::Write(const Handle(Poly_Polygon2D)& P,
215 Standard_OStream& OS,
216 const Standard_Boolean Compact)
218 OS << "Poly_Polygon2D\n";
220 OS << P->NbNodes() << " ";
223 OS << setw(8) << P->NbNodes() << " Nodes\n";
226 // write the deflection
228 if (!Compact) OS << "Deflection : ";
229 OS << P->Deflection() << "\n";
233 if (!Compact) OS << "\nNodes :\n";
235 Standard_Integer i, nbNodes = P->NbNodes();
236 const TColgp_Array1OfPnt2d& Nodes = P->Nodes();
237 for (i = 1; i <= nbNodes; i++) {
238 if (!Compact) OS << setw(10) << i << " : ";
239 if (!Compact) OS << setw(17);
240 OS << Nodes(i).X() << " ";
241 if (!Compact) OS << setw(17);
242 OS << Nodes(i).Y() << "\n";
248 //=======================================================================
251 //=======================================================================
253 void Poly::Dump(const Handle(Poly_Triangulation)& T, Standard_OStream& OS)
255 Poly::Write(T,OS,Standard_False);
259 //=======================================================================
262 //=======================================================================
264 void Poly::Dump(const Handle(Poly_Polygon3D)& P, Standard_OStream& OS)
266 Poly::Write(P,OS,Standard_False);
270 //=======================================================================
273 //=======================================================================
275 void Poly::Dump(const Handle(Poly_Polygon2D)& P, Standard_OStream& OS)
277 Poly::Write(P,OS,Standard_False);
281 //=======================================================================
282 //function : ReadTriangulation
284 //=======================================================================
286 Handle(Poly_Triangulation) Poly::ReadTriangulation(Standard_IStream& IS)
288 // Read a triangulation
292 if (strcmp(line,"Poly_Triangulation")) {
294 cout << "Not a Triangulation in the file" << endl;
296 return Handle(Poly_Triangulation)();
299 Standard_Integer nbNodes, nbTriangles;
300 Standard_Boolean hasUV;
301 IS >> nbNodes >> nbTriangles >> hasUV;
309 TColgp_Array1OfPnt Nodes(1, nbNodes);
310 TColgp_Array1OfPnt2d UVNodes(1, nbNodes);
312 for (i = 1; i <= nbNodes; i++) {
314 Nodes(i).SetCoord(x,y,z);
317 // read the UV points if necessary
320 for (i = 1; i <= nbNodes; i++) {
322 UVNodes(i).SetCoord(x,y);
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);
336 Handle(Poly_Triangulation) T;
338 if (hasUV) T = new Poly_Triangulation(Nodes,UVNodes,Triangles);
339 else T = new Poly_Triangulation(Nodes,Triangles);
347 //=======================================================================
348 //function : ReadPolygon3D
350 //=======================================================================
352 Handle(Poly_Polygon3D) Poly::ReadPolygon3D(Standard_IStream& IS)
358 if (strcmp(line,"Poly_Polygon3D")) {
360 cout << "Not a Polygon3D in the file" << endl;
362 return Handle(Poly_Polygon3D)();
365 Standard_Integer nbNodes;
368 Standard_Boolean hasparameters;
377 TColgp_Array1OfPnt Nodes(1, nbNodes);
379 for (i = 1; i <= nbNodes; i++) {
381 Nodes(i).SetCoord(x,y,z);
384 TColStd_Array1OfReal Param(1,nbNodes);
386 for (i = 1; i <= nbNodes; i++) {
391 Handle(Poly_Polygon3D) P;
393 P = new Poly_Polygon3D(Nodes);
395 P = new Poly_Polygon3D(Nodes, Param);
402 //=======================================================================
403 //function : ReadPolygon3D
405 //=======================================================================
407 Handle(Poly_Polygon2D) Poly::ReadPolygon2D(Standard_IStream& IS)
413 if (strcmp(line,"Poly_Polygon2D")) {
415 cout << "Not a Polygon2D in the file" << endl;
417 return Handle(Poly_Polygon2D)();
420 Standard_Integer nbNodes;
429 TColgp_Array1OfPnt2d Nodes(1, nbNodes);
431 for (i = 1; i <= nbNodes; i++) {
433 Nodes(i).SetCoord(x,y);
436 Handle(Poly_Polygon2D) P =
437 new Poly_Polygon2D(Nodes);
444 //=======================================================================
445 //function : ComputeNormals
447 //=======================================================================
448 void Poly::ComputeNormals (const Handle(Poly_Triangulation)& theTri)
450 const TColgp_Array1OfPnt& aNodes = theTri->Nodes();
451 const Standard_Integer aNbNodes = aNodes.Size();
453 const Handle(TShort_HArray1OfShortReal) aNormals = new TShort_HArray1OfShortReal (1, aNbNodes * 3);
454 aNormals->Init (0.0f);
455 Standard_ShortReal* aNormArr = &aNormals->ChangeFirst();
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())
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]);
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)
471 const Standard_Real aMod = aTriNorm.SquareModulus();
474 aTriNorm /= Sqrt (aMod);
482 for (Standard_Integer aNodeIter = 0; aNodeIter < 3; ++aNodeIter)
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());
491 // Normalize all vectors
493 for (Standard_Integer aNodeIter = 0; aNodeIter < aNbNodes; ++aNodeIter)
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();
500 aNormArr[anIndex + 0] = 0.0f;
501 aNormArr[anIndex + 1] = 0.0f;
502 aNormArr[anIndex + 2] = 1.0f;
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());
513 theTri->SetNormals (aNormals);
516 //=======================================================================
517 //function : PointOnTriangle
519 //=======================================================================
521 Standard_Real Poly::PointOnTriangle (const gp_XY& theP1, const gp_XY& theP2, const gp_XY& theP3,
522 const gp_XY& theP, gp_XY& theUV)
524 gp_XY aDP = theP - theP1;
525 gp_XY aDU = theP2 - theP1;
526 gp_XY aDV = theP3 - theP1;
527 Standard_Real aDet = aDU ^ aDV;
529 // case of non-degenerated triangle
530 if ( Abs (aDet) > gp::Resolution() )
532 Standard_Real aU = (aDP ^ aDV) / aDet;
533 Standard_Real aV = -(aDP ^ aDU) / aDet;
535 // if point is inside triangle, just return parameters
536 if ( aU > -gp::Resolution() &&
537 aV > -gp::Resolution() &&
538 1. - aU - aV > -gp::Resolution() )
540 theUV.SetCoord (aU, aV);
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
548 // project on side U=0
550 aV = Min (1., Max (0., (aDP * aDV) / aDV.SquareModulus()));
551 Standard_Real aD = (aV * aDV - aDP).SquareModulus();
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();
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();
574 theUV.SetCoord (aU, aV);
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
583 if ( aL2V < gp::Resolution() ) // whole triangle is degenerated to point
585 theUV.SetCoord (0., 0.);
586 return (theP - theP1).SquareModulus();
590 theUV.SetCoord (0., (aDP * aDV) / aL2V);
591 return (theP - (theP1 + theUV.Y() * aDV)).SquareModulus();
594 else if ( aL2V < gp::Resolution() ) // side 1-3 is degenerated
596 theUV.SetCoord ((aDP * aDU) / aL2U, 0.);
597 return (theP - (theP1 + theUV.X() * aDU)).SquareModulus();
599 else // sides 1-2 and 1-3 are collinear
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();
608 theUV.SetCoord ((aDP * aDU) / aL2U, 0.);
613 theUV.SetCoord (0., (aDP * aDV) / aL2V);