2 // Created: Mon Mar 6 11:02:24 1995
3 // Author: Laurent PAINNOT
6 #include <Standard_Stream.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>
17 #include <Poly_Polygon3D.hxx>
18 #include <Poly_Polygon2D.hxx>
19 #include <Precision.hxx>
20 #include <TShort_Array1OfShortReal.hxx>
21 #include <TShort_HArray1OfShortReal.hxx>
23 //=======================================================================
25 //purpose : Join several triangulations to one new triangulation object
26 //=======================================================================
28 Handle(Poly_Triangulation) Poly::Catenate (const Poly_ListOfTriangulation& lstTri)
30 Standard_Integer nNodes(0);
31 Standard_Integer nTrian(0);
33 // Sum up the total number of nodes.
34 Poly_ListOfTriangulation::Iterator anIter(lstTri);
35 for (; anIter.More(); anIter.Next()) {
36 const Handle(Poly_Triangulation)& aTri = anIter.Value();
37 if (aTri.IsNull() == Standard_False) {
38 nNodes += aTri->NbNodes();
39 nTrian += aTri->NbTriangles();
43 Handle(Poly_Triangulation) aResult;
45 aResult = new Poly_Triangulation(nNodes, nTrian, Standard_False);
46 Standard_Integer i, iNode[3];
49 TColgp_Array1OfPnt& arrNode = aResult->ChangeNodes();
50 Poly_Array1OfTriangle& arrTrian = aResult->ChangeTriangles();
51 for (anIter.Init(lstTri); anIter.More(); anIter.Next()) {
52 const Handle(Poly_Triangulation)& aTri = anIter.Value();
53 if (aTri.IsNull() == Standard_False) {
54 const TColgp_Array1OfPnt& srcNode = aTri->Nodes();
55 const Poly_Array1OfTriangle& srcTrian = aTri->Triangles();
56 const Standard_Integer nbNodes = aTri->NbNodes();
57 const Standard_Integer nbTrian = aTri->NbTriangles();
58 for (i = 1; i <= nbNodes; i++) {
59 arrNode.SetValue(i + nNodes, srcNode(i));
61 for (i = 1; i <= nbTrian; i++) {
62 srcTrian(i).Get(iNode[0], iNode[1], iNode[2]);
63 arrTrian.SetValue(i + nTrian, Poly_Triangle(iNode[0] + nNodes,
75 //=======================================================================
78 //=======================================================================
80 void Poly::Write(const Handle(Poly_Triangulation)& T,
82 const Standard_Boolean Compact)
84 OS << "Poly_Triangulation\n";
86 OS << T->NbNodes() << " " << T->NbTriangles() << " ";
87 OS << ((T->HasUVNodes()) ? "1" : "0") << "\n";
90 OS << setw(8) << T->NbNodes() << " Nodes\n";
91 OS << setw(8) << T->NbTriangles() << " Triangles\n";
92 OS << ((T->HasUVNodes()) ? "with" : "without") << " UV nodes\n";
95 // write the deflection
97 if (!Compact) OS << "Deflection : ";
98 OS << T->Deflection() << "\n";
100 // write the 3d nodes
102 if (!Compact) OS << "\n3D Nodes :\n";
104 Standard_Integer i, nbNodes = T->NbNodes();
105 const TColgp_Array1OfPnt& Nodes = T->Nodes();
106 for (i = 1; i <= nbNodes; i++) {
107 if (!Compact) OS << setw(10) << i << " : ";
108 if (!Compact) OS << setw(17);
109 OS << Nodes(i).X() << " ";
110 if (!Compact) OS << setw(17);
111 OS << Nodes(i).Y() << " ";
112 if (!Compact) OS << setw(17);
113 OS << Nodes(i).Z() << "\n";
116 if (T->HasUVNodes()) {
117 if (!Compact) OS << "\nUV Nodes :\n";
118 const TColgp_Array1OfPnt2d& UVNodes = T->UVNodes();
119 for (i = 1; i <= nbNodes; i++) {
120 if (!Compact) OS << setw(10) << i << " : ";
121 if (!Compact) OS << setw(17);
122 OS << UVNodes(i).X() << " ";
123 if (!Compact) OS << setw(17);
124 OS << UVNodes(i).Y() << "\n";
128 if (!Compact) OS << "\nTriangles :\n";
129 Standard_Integer nbTriangles = T->NbTriangles();
130 Standard_Integer n1, n2, n3;
131 const Poly_Array1OfTriangle& Triangles = T->Triangles();
132 for (i = 1; i <= nbTriangles; i++) {
133 if (!Compact) OS << setw(10) << i << " : ";
134 Triangles(i).Get(n1, n2, n3);
135 if (!Compact) OS << setw(10);
137 if (!Compact) OS << setw(10);
139 if (!Compact) OS << setw(10);
145 //=======================================================================
148 //=======================================================================
150 void Poly::Write(const Handle(Poly_Polygon3D)& P,
151 Standard_OStream& OS,
152 const Standard_Boolean Compact)
154 OS << "Poly_Polygon3D\n";
156 OS << P->NbNodes() << " ";
157 OS << ((P->HasParameters()) ? "1" : "0") << "\n";
160 OS << setw(8) << P->NbNodes() << " Nodes\n";
161 OS << ((P->HasParameters()) ? "with" : "without") << " parameters\n";
164 // write the deflection
166 if (!Compact) OS << "Deflection : ";
167 OS << P->Deflection() << "\n";
171 if (!Compact) OS << "\nNodes :\n";
173 Standard_Integer i, nbNodes = P->NbNodes();
174 const TColgp_Array1OfPnt& Nodes = P->Nodes();
175 for (i = 1; i <= nbNodes; i++) {
176 if (!Compact) OS << setw(10) << i << " : ";
177 if (!Compact) OS << setw(17);
178 OS << Nodes(i).X() << " ";
179 if (!Compact) OS << setw(17);
180 OS << Nodes(i).Y() << " ";
181 if (!Compact) OS << setw(17);
182 OS << Nodes(i).Z() << "\n";
185 if (P->HasParameters()) {
186 if (!Compact) OS << "\nParameters :\n";
187 const TColStd_Array1OfReal& Param = P->Parameters();
188 for (i = 1; i <= nbNodes; i++) {
189 OS << Param(i) << " ";
198 //=======================================================================
201 //=======================================================================
203 void Poly::Write(const Handle(Poly_Polygon2D)& P,
204 Standard_OStream& OS,
205 const Standard_Boolean Compact)
207 OS << "Poly_Polygon2D\n";
209 OS << P->NbNodes() << " ";
212 OS << setw(8) << P->NbNodes() << " Nodes\n";
215 // write the deflection
217 if (!Compact) OS << "Deflection : ";
218 OS << P->Deflection() << "\n";
222 if (!Compact) OS << "\nNodes :\n";
224 Standard_Integer i, nbNodes = P->NbNodes();
225 const TColgp_Array1OfPnt2d& Nodes = P->Nodes();
226 for (i = 1; i <= nbNodes; i++) {
227 if (!Compact) OS << setw(10) << i << " : ";
228 if (!Compact) OS << setw(17);
229 OS << Nodes(i).X() << " ";
230 if (!Compact) OS << setw(17);
231 OS << Nodes(i).Y() << "\n";
237 //=======================================================================
240 //=======================================================================
242 void Poly::Dump(const Handle(Poly_Triangulation)& T, Standard_OStream& OS)
244 Poly::Write(T,OS,Standard_False);
248 //=======================================================================
251 //=======================================================================
253 void Poly::Dump(const Handle(Poly_Polygon3D)& P, Standard_OStream& OS)
255 Poly::Write(P,OS,Standard_False);
259 //=======================================================================
262 //=======================================================================
264 void Poly::Dump(const Handle(Poly_Polygon2D)& P, Standard_OStream& OS)
266 Poly::Write(P,OS,Standard_False);
270 //=======================================================================
271 //function : ReadTriangulation
273 //=======================================================================
275 Handle(Poly_Triangulation) Poly::ReadTriangulation(Standard_IStream& IS)
277 // Read a triangulation
281 if (strcmp(line,"Poly_Triangulation")) {
282 cout << "Not a Triangulation in the file" << endl;
283 return Handle(Poly_Triangulation)();
286 Standard_Integer nbNodes, nbTriangles;
287 Standard_Boolean hasUV;
288 IS >> nbNodes >> nbTriangles >> hasUV;
296 TColgp_Array1OfPnt Nodes(1, nbNodes);
297 TColgp_Array1OfPnt2d UVNodes(1, nbNodes);
299 for (i = 1; i <= nbNodes; i++) {
301 Nodes(i).SetCoord(x,y,z);
304 // read the UV points if necessary
307 for (i = 1; i <= nbNodes; i++) {
309 UVNodes(i).SetCoord(x,y);
314 // read the triangles
315 Standard_Integer n1,n2,n3;
316 Poly_Array1OfTriangle Triangles(1, nbTriangles);
317 for (i = 1; i <= nbTriangles; i++) {
318 IS >> n1 >> n2 >> n3;
319 Triangles(i).Set(n1,n2,n3);
323 Handle(Poly_Triangulation) T;
325 if (hasUV) T = new Poly_Triangulation(Nodes,UVNodes,Triangles);
326 else T = new Poly_Triangulation(Nodes,Triangles);
334 //=======================================================================
335 //function : ReadPolygon3D
337 //=======================================================================
339 Handle(Poly_Polygon3D) Poly::ReadPolygon3D(Standard_IStream& IS)
345 if (strcmp(line,"Poly_Polygon3D")) {
346 cout << "Not a Polygon3D in the file" << endl;
347 return Handle(Poly_Polygon3D)();
350 Standard_Integer nbNodes;
353 Standard_Boolean hasparameters;
362 TColgp_Array1OfPnt Nodes(1, nbNodes);
364 for (i = 1; i <= nbNodes; i++) {
366 Nodes(i).SetCoord(x,y,z);
369 TColStd_Array1OfReal Param(1,nbNodes);
371 for (i = 1; i <= nbNodes; i++) {
376 Handle(Poly_Polygon3D) P;
378 P = new Poly_Polygon3D(Nodes);
380 P = new Poly_Polygon3D(Nodes, Param);
387 //=======================================================================
388 //function : ReadPolygon3D
390 //=======================================================================
392 Handle(Poly_Polygon2D) Poly::ReadPolygon2D(Standard_IStream& IS)
398 if (strcmp(line,"Poly_Polygon2D")) {
399 cout << "Not a Polygon2D in the file" << endl;
400 return Handle(Poly_Polygon2D)();
403 Standard_Integer nbNodes;
412 TColgp_Array1OfPnt2d Nodes(1, nbNodes);
414 for (i = 1; i <= nbNodes; i++) {
416 Nodes(i).SetCoord(x,y);
419 Handle(Poly_Polygon2D) P =
420 new Poly_Polygon2D(Nodes);
427 //=======================================================================
428 //function : ComputeNormals
430 //=======================================================================
432 void Poly::ComputeNormals(const Handle(Poly_Triangulation)& Tri)
434 const TColgp_Array1OfPnt& arrNodes = Tri->Nodes();
435 const Poly_Array1OfTriangle & arrTri = Tri->Triangles();
436 Standard_Integer nbNormVal = Tri->NbNodes() * 3;
437 const Handle(TShort_HArray1OfShortReal) Normals =
438 new TShort_HArray1OfShortReal(1, nbNormVal);
441 Standard_ShortReal * arrNormal = &(Normals->ChangeValue(1));
443 Standard_Real aCoord[3];
444 Standard_Integer iNode[3] = {0, 0, 0};
445 Standard_Integer iN, iTri;
446 const Standard_Real eps2 = Precision::Confusion()*Precision::Confusion();
448 for (iTri = 1; iTri <= arrTri.Length(); iTri++) {
449 // Get the nodes of the current triangle
450 arrTri(iTri).Get (iNode[0], iNode[1], iNode[2]);
451 const gp_XYZ aVec[2] = {
452 arrNodes(iNode[1]).XYZ() - arrNodes(iNode[0]).XYZ(),
453 arrNodes(iNode[2]).XYZ() - arrNodes(iNode[0]).XYZ()
456 // Find the normal vector of the current triangle
457 gp_XYZ aNorm = aVec[0] ^ aVec[1];
458 const Standard_Real aMod = aNorm.SquareModulus();
461 aNorm.Coord (aCoord[0], aCoord[1], aCoord[2]);
462 iNode[0] = (iNode[0]-1)*3;
463 iNode[1] = (iNode[1]-1)*3;
464 iNode[2] = (iNode[2]-1)*3;
465 arrNormal[iNode[0]+0] += (Standard_ShortReal)aCoord[0];
466 arrNormal[iNode[0]+1] += (Standard_ShortReal)aCoord[1];
467 arrNormal[iNode[0]+2] += (Standard_ShortReal)aCoord[2];
468 arrNormal[iNode[1]+0] += (Standard_ShortReal)aCoord[0];
469 arrNormal[iNode[1]+1] += (Standard_ShortReal)aCoord[1];
470 arrNormal[iNode[1]+2] += (Standard_ShortReal)aCoord[2];
471 arrNormal[iNode[2]+0] += (Standard_ShortReal)aCoord[0];
472 arrNormal[iNode[2]+1] += (Standard_ShortReal)aCoord[1];
473 arrNormal[iNode[2]+2] += (Standard_ShortReal)aCoord[2];
476 // Normalize all vectors
477 for (iN = 0; iN < nbNormVal; iN+=3) {
478 Standard_Real aMod (arrNormal[iN+0]*arrNormal[iN+0] +
479 arrNormal[iN+1]*arrNormal[iN+1] +
480 arrNormal[iN+2]*arrNormal[iN+2]);
482 arrNormal[iN+0] = 0.f;
483 arrNormal[iN+1] = 0.f;
484 arrNormal[iN+2] = 1.f;
487 arrNormal[iN+0] = Standard_ShortReal(arrNormal[iN+0]/aMod);
488 arrNormal[iN+1] = Standard_ShortReal(arrNormal[iN+1]/aMod);
489 arrNormal[iN+2] = Standard_ShortReal(arrNormal[iN+2]/aMod);
493 Tri->SetNormals(Normals);
496 //=======================================================================
497 //function : PointOnTriangle
499 //=======================================================================
501 Standard_Real Poly::PointOnTriangle (const gp_XY& theP1, const gp_XY& theP2, const gp_XY& theP3,
502 const gp_XY& theP, gp_XY& theUV)
504 gp_XY aDP = theP - theP1;
505 gp_XY aDU = theP2 - theP1;
506 gp_XY aDV = theP3 - theP1;
507 Standard_Real aDet = aDU ^ aDV;
509 // case of non-degenerated triangle
510 if ( Abs (aDet) > gp::Resolution() )
512 Standard_Real aU = (aDP ^ aDV) / aDet;
513 Standard_Real aV = -(aDP ^ aDU) / aDet;
515 // if point is inside triangle, just return parameters
516 if ( aU > -gp::Resolution() &&
517 aV > -gp::Resolution() &&
518 1. - aU - aV > -gp::Resolution() )
520 theUV.SetCoord (aU, aV);
524 // else find closest point on triangle sides; note that in general case
525 // triangle can be very distorted and it is necessary to check
526 // projection on all sides regardless of values of computed parameters
528 // project on side U=0
530 aV = Min (1., Max (0., (aDP * aDV) / aDV.SquareModulus()));
531 Standard_Real aD = (aV * aDV - aDP).SquareModulus();
533 // project on side V=0
534 Standard_Real u = Min (1., Max (0., (aDP * aDU) / aDU.SquareModulus()));
535 Standard_Real d = (u * aDU - aDP).SquareModulus();
543 // project on side U+V=1
544 gp_XY aDUV = aDV - aDU;
545 Standard_Real v = Min (1., Max (0., ((aDP - aDU) * aDUV) / aDUV.SquareModulus()));
546 d = (theP2 + v * aDUV - theP).SquareModulus();
554 theUV.SetCoord (aU, aV);
558 // degenerated triangle
559 Standard_Real aL2U = aDU.SquareModulus();
560 Standard_Real aL2V = aDV.SquareModulus();
561 if ( aL2U < gp::Resolution() ) // side 1-2 is degenerated
563 if ( aL2V < gp::Resolution() ) // whole triangle is degenerated to point
565 theUV.SetCoord (0., 0.);
566 return (theP - theP1).SquareModulus();
570 theUV.SetCoord (0., (aDP * aDV) / aL2V);
571 return (theP - (theP1 + theUV.Y() * aDV)).SquareModulus();
574 else if ( aL2V < gp::Resolution() ) // side 1-3 is degenerated
576 theUV.SetCoord ((aDP * aDU) / aL2U, 0.);
577 return (theP - (theP1 + theUV.X() * aDU)).SquareModulus();
579 else // sides 1-2 and 1-3 are collinear
581 // select parameter on one of sides so as to have points closer to picked
582 Standard_Real aU = Min (1., Max (0., (aDP * aDU) / aL2U));
583 Standard_Real aV = Min (1., Max (0., (aDP * aDV) / aL2V));
584 Standard_Real aD1 = (aDP - aU * aDU).SquareModulus();
585 Standard_Real aD2 = (aDP - aV * aDV).SquareModulus();
588 theUV.SetCoord ((aDP * aDU) / aL2U, 0.);
593 theUV.SetCoord (0., (aDP * aDV) / aL2V);