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 |
39 | Handle(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 |
87 | void 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 |
154 | void 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 |
207 | void 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 | |
246 | void 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 | |
257 | void 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 | |
268 | void 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 | |
279 | Handle(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 | |
345 | Handle(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 | |
400 | Handle(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 | |
442 | void 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 | |
509 | Standard_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 | |