1 // Created on: 1993-02-03
2 // Created by: Laurent BUCHARD
3 // Copyright (c) 1993-1999 Matra Datavision
4 // Copyright (c) 1999-2012 OPEN CASCADE SAS
6 // The content of this file is subject to the Open CASCADE Technology Public
7 // License Version 6.5 (the "License"). You may not use the content of this file
8 // except in compliance with the License. Please obtain a copy of the License
9 // at http://www.opencascade.org and read it completely before using this file.
11 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
12 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
14 // The Original Code and all software distributed under the License is
15 // distributed on an "AS IS" basis, without warranty of any kind, and the
16 // Initial Developer hereby disclaims all such warranties, including without
17 // limitation, any warranties of merchantability, fitness for a particular
18 // purpose or non-infringement. Please see the License for the specific terms
19 // and conditions governing the rights and limitations under the License.
22 #include <IntPatch_Polyhedron.ixx>
24 #include <IntPatch_HInterTool.hxx>
28 #include <TColgp_Array2OfPnt.hxx>
29 #include <TColStd_Array2OfReal.hxx>
30 #include <Bnd_Array1OfBox.hxx>
31 #include <Standard_ConstructionError.hxx>
32 #include <Precision.hxx>
37 #define LONGUEUR_MINI_EDGE_TRIANGLE 1e-14
38 #define DEFLECTION_COEFF 1.1
41 //================================================================================
42 static Standard_Integer NbPOnU (const Handle(Adaptor3d_HSurface)& S)
44 const Standard_Real u0 = S->FirstUParameter();
45 const Standard_Real u1 = S->LastUParameter();
46 const Standard_Integer nbpu = IntPatch_HInterTool::NbSamplesU(S,u0,u1);
47 return (nbpu>NBMAXUV? NBMAXUV : nbpu);
49 //================================================================================
50 static Standard_Integer NbPOnV (const Handle(Adaptor3d_HSurface)& S)
52 const Standard_Real v0 = S->FirstVParameter();
53 const Standard_Real v1 = S->LastVParameter();
54 const Standard_Integer nbpv = IntPatch_HInterTool::NbSamplesV(S,v0,v1);
55 return (nbpv>NBMAXUV? NBMAXUV : nbpv);
58 //=======================================================================
61 //=======================================================================
62 void IntPatch_Polyhedron::Destroy()
64 gp_Pnt *CMyPnts = (gp_Pnt *)C_MyPnts; if(C_MyPnts) delete [] CMyPnts;
65 Standard_Real *CMyU = (Standard_Real *)C_MyU; if(C_MyU) delete [] CMyU;
66 Standard_Real *CMyV = (Standard_Real *)C_MyV; if(C_MyV) delete [] CMyV;
67 C_MyPnts=C_MyU=C_MyV=NULL;
70 //=======================================================================
71 //function : IntPatch_Polyhedron
73 //=======================================================================
74 IntPatch_Polyhedron::IntPatch_Polyhedron (const Handle(Adaptor3d_HSurface)& Surface)
75 : TheDeflection(Epsilon(100.)),
76 nbdeltaU(NbPOnU(Surface)),
77 nbdeltaV(NbPOnV(Surface)),
78 C_MyPnts(NULL),C_MyU(NULL),C_MyV(NULL),
79 UMinSingular(IntPatch_HInterTool::SingularOnVMin(Surface)),
80 UMaxSingular(IntPatch_HInterTool::SingularOnVMin(Surface)),
81 VMinSingular(IntPatch_HInterTool::SingularOnVMin(Surface)),
82 VMaxSingular(IntPatch_HInterTool::SingularOnVMin(Surface))
84 const Standard_Integer t = (nbdeltaU+1)*(nbdeltaV+1)+1;
85 gp_Pnt *CMyPnts = new gp_Pnt[t];
86 Standard_Real *CMyU = new Standard_Real[t];
87 Standard_Real *CMyV = new Standard_Real[t];
92 const Standard_Real u0 = Surface->FirstUParameter();
93 const Standard_Real u1 = Surface->LastUParameter();
94 const Standard_Real v0 = Surface->FirstVParameter();
95 const Standard_Real v1 = Surface->LastVParameter();
97 const Standard_Real U1mU0sNbdeltaU = (u1-u0)/(Standard_Real)nbdeltaU;
98 const Standard_Real V1mV0sNbdeltaV = (v1-v0)/(Standard_Real)nbdeltaV;
102 Standard_Integer i1, i2, Index=1;
103 for (i1 = 0, U = u0; i1 <= nbdeltaU; i1++, U+= U1mU0sNbdeltaU) {
104 for (i2 = 0, V = v0; i2 <= nbdeltaV; i2++, V+= V1mV0sNbdeltaV ) {
114 Standard_Real tol=0.0;
115 const Standard_Integer nbtriangles = NbTriangles();
116 for (i1=1; i1<=nbtriangles; i1++) {
117 const Standard_Real tol1 = DeflectionOnTriangle(Surface,i1);
118 if(tol1>tol) tol=tol1;
121 tol*=DEFLECTION_COEFF;
123 DeflectionOverEstimation(tol);
127 //=======================================================================
128 //function : IntPatch_Polyhedron
130 //=======================================================================
131 IntPatch_Polyhedron::IntPatch_Polyhedron (const Handle(Adaptor3d_HSurface)& Surface,
132 const Standard_Integer nbu,
133 const Standard_Integer nbv)
134 : TheDeflection(Epsilon(100.)),
137 C_MyPnts(NULL),C_MyU(NULL),C_MyV(NULL),
138 UMinSingular(IntPatch_HInterTool::SingularOnVMin(Surface)),
139 UMaxSingular(IntPatch_HInterTool::SingularOnVMin(Surface)),
140 VMinSingular(IntPatch_HInterTool::SingularOnVMin(Surface)),
141 VMaxSingular(IntPatch_HInterTool::SingularOnVMin(Surface))
143 const Standard_Integer t = (nbdeltaU+1)*(nbdeltaV+1)+1;
144 gp_Pnt *CMyPnts = new gp_Pnt[t];
145 Standard_Real *CMyU = new Standard_Real[t];
146 Standard_Real *CMyV = new Standard_Real[t];
151 const Standard_Real u0 = Surface->FirstUParameter();
152 const Standard_Real u1 = Surface->LastUParameter();
153 const Standard_Real v0 = Surface->FirstVParameter();
154 const Standard_Real v1 = Surface->LastVParameter();
156 const Standard_Real U1mU0sNbdeltaU = (u1-u0)/(Standard_Real)nbdeltaU;
157 const Standard_Real V1mV0sNbdeltaV = (v1-v0)/(Standard_Real)nbdeltaV;
161 Standard_Integer i1, i2, Index=1;
162 for (i1 = 0, U = u0; i1 <= nbdeltaU; i1++, U+= U1mU0sNbdeltaU) {
163 for (i2 = 0, V = v0; i2 <= nbdeltaV; i2++, V+= V1mV0sNbdeltaV ) {
173 Standard_Real tol=0.0;
174 const Standard_Integer nbtriangles = NbTriangles();
175 for (i1=1; i1<=nbtriangles; i1++) {
176 const Standard_Real tol1 = DeflectionOnTriangle(Surface,i1);
177 if(tol1>tol) tol=tol1;
180 tol*=DEFLECTION_COEFF;
182 DeflectionOverEstimation(tol);
187 //=======================================================================
188 //function : DeflectionOnTriangle
190 //=======================================================================
192 Standard_Real IntPatch_Polyhedron::DeflectionOnTriangle
193 (const Handle(Adaptor3d_HSurface)& Surface,
194 const Standard_Integer Triang) const
196 Standard_Integer i1,i2,i3;
198 Triangle(Triang,i1,i2,i3);
199 //-- Calcul de l eqution du plan
200 Standard_Real u1,v1,u2,v2,u3,v3;
202 P1 = Point(i1,u1,v1);
203 P2 = Point(i2,u2,v2);
204 P3 = Point(i3,u3,v3);
205 if(P1.SquareDistance(P2)<=LONGUEUR_MINI_EDGE_TRIANGLE) return(0);
206 if(P1.SquareDistance(P3)<=LONGUEUR_MINI_EDGE_TRIANGLE) return(0);
207 if(P2.SquareDistance(P3)<=LONGUEUR_MINI_EDGE_TRIANGLE) return(0);
208 gp_XYZ XYZ1=P2.XYZ()-P1.XYZ();
209 gp_XYZ XYZ2=P3.XYZ()-P2.XYZ();
210 gp_XYZ XYZ3=P1.XYZ()-P3.XYZ();
211 gp_Vec NormalVector((XYZ1^XYZ2)+(XYZ2^XYZ3)+(XYZ3^XYZ1));
212 NormalVector.Normalize();
213 //-- Calcul du point u,v au centre du triangle
214 Standard_Real u = (u1+u2+u3)/3.0;
215 Standard_Real v = (v1+v2+v3)/3.0;
216 gp_Vec P1P(P1,Surface->Value(u,v));
217 return(Abs(P1P.Dot(NormalVector)));
220 //=======================================================================
221 //function : Parameters
223 //=======================================================================
224 void IntPatch_Polyhedron::Parameters( const Standard_Integer Index
226 ,Standard_Real &V) const
228 U = ((Standard_Real *)C_MyU)[Index];
229 V = ((Standard_Real *)C_MyV)[Index];
232 //=======================================================================
233 //function : DeflectionOverEstimation
235 //=======================================================================
236 void IntPatch_Polyhedron::DeflectionOverEstimation(const Standard_Real flec)
239 TheDeflection=0.0001;
240 TheBnd.Enlarge(0.0001);
244 TheBnd.Enlarge(flec);
248 //=======================================================================
249 //function : DeflectionOverEstimation
251 //=======================================================================
252 Standard_Real IntPatch_Polyhedron::DeflectionOverEstimation() const
254 return TheDeflection;
257 //=======================================================================
258 //function : Bounding
260 //=======================================================================
261 const Bnd_Box& IntPatch_Polyhedron::Bounding() const
266 //=======================================================================
267 //function : FillBounding
269 //=======================================================================
270 void IntPatch_Polyhedron::FillBounding()
272 TheComponentsBnd=new Bnd_HArray1OfBox(1, NbTriangles());
274 Standard_Integer p1, p2, p3;
275 Standard_Integer nbtriangles = NbTriangles();
276 for (Standard_Integer iTri=1; iTri<=nbtriangles; iTri++) {
277 Triangle(iTri, p1, p2, p3);
279 const gp_Pnt& P1 = Point(p1);
280 const gp_Pnt& P2 = Point(p2);
281 const gp_Pnt& P3 = Point(p3);
282 if(P1.SquareDistance(P2)>LONGUEUR_MINI_EDGE_TRIANGLE) {
283 if(P1.SquareDistance(P3)>LONGUEUR_MINI_EDGE_TRIANGLE) {
284 if(P2.SquareDistance(P3)>LONGUEUR_MINI_EDGE_TRIANGLE) {
291 Boite.Enlarge(TheDeflection);
292 TheComponentsBnd->SetValue(iTri,Boite);
296 //=======================================================================
297 //function : ComponentsBounding
299 //=======================================================================
300 const Handle(Bnd_HArray1OfBox)& IntPatch_Polyhedron::ComponentsBounding () const
302 return TheComponentsBnd;
305 //=======================================================================
306 //function : NbTriangles
308 //=======================================================================
309 Standard_Integer IntPatch_Polyhedron::NbTriangles () const
311 return nbdeltaU*nbdeltaV*2;
314 //=======================================================================
315 //function : NbPoints
317 //=======================================================================
318 Standard_Integer IntPatch_Polyhedron::NbPoints () const
320 return (nbdeltaU+1)*(nbdeltaV+1);
323 //=======================================================================
324 //function : TriConnex
326 //=======================================================================
327 Standard_Integer IntPatch_Polyhedron::TriConnex (const Standard_Integer Triang,
328 const Standard_Integer Pivot,
329 const Standard_Integer Pedge,
330 Standard_Integer& TriCon,
331 Standard_Integer& OtherP) const {
333 Standard_Integer Pivotm1 = Pivot-1;
334 Standard_Integer nbdeltaVp1 = nbdeltaV+1;
335 Standard_Integer nbdeltaVm2 = nbdeltaV + nbdeltaV;
337 // Pivot position in the MaTriangle :
338 Standard_Integer ligP = Pivotm1/nbdeltaVp1;
339 Standard_Integer colP = Pivotm1 - ligP * nbdeltaVp1;
341 // Point sur Edge position in the MaTriangle and edge typ :
342 Standard_Integer ligE = 0, colE = 0, typE = 0;
344 ligE= (Pedge-1)/nbdeltaVp1;
345 colE= (Pedge-1) - (ligE * nbdeltaVp1);
347 if (ligP==ligE) typE=1;
349 else if (colP==colE) typE=2;
357 // Triangle position General case :
358 Standard_Integer linT = 0, colT = 0;
359 Standard_Integer linO = 0, colO = 0;
360 Standard_Integer t,tt;
362 t = (Triang-1)/(nbdeltaVm2);
363 tt= (Triang-1)-t*nbdeltaVm2;
373 if (colT==ligP+ligP) {
386 case 1: // Horizontal
390 colO=(colP>colE)? colP : colE; //--colO=Max(colP, colE);
395 colO=(colP<colE)? colP : colE; //--colO=Min(colP, colE);
399 if (colT==(colP+colP)) {
401 linO=(ligP>ligE)? ligP : ligE; //--linO=Max(ligP, ligE);
406 linO=(ligP<ligE)? ligP : ligE; //--linO=Min(ligP, ligE);
413 linO=(ligP>ligE)? ligP : ligE; //--linO=Max(ligP, ligE);
414 colO=(colP<colE)? colP : colE; //--colO=Min(colP, colE);
418 linO=(ligP<ligE)? ligP : ligE; //--linO=Min(ligP, ligE);
419 colO=(colP>colE)? colP : colE; //--colO=Max(colP, colE);
425 // Unknown Triangle position :
428 linT=(1>ligP)? 1 : ligP; //--linT=Max(1, ligP);
429 colT=(1>(colP+colP))? 1 : (colP+colP); //--colT=Max(1, colP+colP);
430 if (ligP==0) linO=ligP+1;
435 // Known edge We take the left or down connectivity :
437 case 1: // Horizontal
439 colT=(colP>colE)? colP : colE; //--colT=Max(colP,colE);
442 colO=(colP>colE)? colP : colE; //--colO=Max(colP,colE);
445 linT=(ligP>ligE)? ligP : ligE; //--linT=Max(ligP, ligE);
447 linO=(ligP<ligE)? ligP : ligE; //--linO=Min(ligP, ligE);
451 linT=(ligP>ligE)? ligP : ligE; //--linT=Max(ligP, ligE);
453 linO=(ligP>ligE)? ligP : ligE; //--linO=Max(ligP, ligE);
454 colO=(colP<colE)? colP : colE; //--colO=Min(colP, colE);
460 TriCon=(linT-1)*nbdeltaVm2 + colT;
465 if (colO<0) {colO=0;linO=1;}
466 else if (colO>nbdeltaV) {colO=nbdeltaV;linO=1;}
469 else if (linT>nbdeltaU) {
472 if (colO<0) {colO=0;linO=nbdeltaU-1;}
473 else if (colO>nbdeltaV) {colO=nbdeltaV;linO=nbdeltaU-1;}
480 if (linO<0) {linO=0;colO=1;}
481 else if (linO>nbdeltaU) {linO=nbdeltaU;colO=1;}
484 else if (colT>nbdeltaV) {
487 if (linO<0) {linO=0;colO=nbdeltaV-1;}
488 else if (linO>nbdeltaU) {linO=nbdeltaU;colO=nbdeltaV-1;}
492 OtherP=linO*nbdeltaVp1 + colO+1;
495 //----------------------------------------------------
496 //-- Detection des cas ou le triangle retourne est
497 //-- invalide. Dans ce cas, on retourne le triangle
498 //-- suivant par un nouvel appel a TriConnex.
500 //-- Si En entree : Point(Pivot)==Point(Pedge)
501 //-- Alors on retourne OtherP a 0
502 //-- et Tricon = Triangle
504 if(Point(Pivot).SquareDistance(Point(Pedge))<=LONGUEUR_MINI_EDGE_TRIANGLE) {
508 cout<<" Probleme ds IntCurveSurface_Polyhedron : Pivot et PEdge Confondus "<<endl;
512 if(Point(OtherP).SquareDistance(Point(Pedge))<=LONGUEUR_MINI_EDGE_TRIANGLE) {
514 cout<<" Probleme ds IntCurveSurface_Polyhedron : OtherP et PEdge Confondus "<<endl;
516 Standard_Integer TempTri,TempOtherP;
520 return(0); //-- BUG NON CORRIGE ( a revoir le role de nbdeltaU et nbdeltaV)
522 return(TriConnex(TempTri,Pivot,TempOtherP,TriCon,OtherP));
529 //=======================================================================
530 //function : PlaneEquation
532 //=======================================================================
534 void IntPatch_Polyhedron::PlaneEquation (const Standard_Integer Triang,
535 gp_XYZ& NormalVector,
536 Standard_Real& PolarDistance) const
538 Standard_Integer i1,i2,i3;
539 Triangle(Triang,i1,i2,i3);
541 gp_XYZ Pointi1(Point(i1).XYZ());
542 gp_XYZ Pointi2(Point(i2).XYZ());
543 gp_XYZ Pointi3(Point(i3).XYZ());
546 gp_XYZ v1= Pointi2 - Pointi1;
547 gp_XYZ v2= Pointi3 - Pointi2;
548 gp_XYZ v3= Pointi1 - Pointi3;
550 if(v1.SquareModulus()<=LONGUEUR_MINI_EDGE_TRIANGLE) { NormalVector.SetCoord(1.0,0.0,0.0); return; }
551 if(v2.SquareModulus()<=LONGUEUR_MINI_EDGE_TRIANGLE) { NormalVector.SetCoord(1.0,0.0,0.0); return; }
552 if(v3.SquareModulus()<=LONGUEUR_MINI_EDGE_TRIANGLE) { NormalVector.SetCoord(1.0,0.0,0.0); return; }
554 NormalVector= (v1^v2)+(v2^v3)+(v3^v1);
555 NormalVector.Normalize();
556 PolarDistance = NormalVector * Point(i1).XYZ();
558 //=======================================================================
561 //=======================================================================
562 Standard_Boolean IntPatch_Polyhedron::Contain (const Standard_Integer Triang,
563 const gp_Pnt& ThePnt) const
565 Standard_Integer i1,i2,i3;
566 Triangle(Triang,i1,i2,i3);
567 gp_XYZ Pointi1(Point(i1).XYZ());
568 gp_XYZ Pointi2(Point(i2).XYZ());
569 gp_XYZ Pointi3(Point(i3).XYZ());
571 gp_XYZ v1=(Pointi2-Pointi1)^(ThePnt.XYZ()-Pointi1);
572 gp_XYZ v2=(Pointi3-Pointi2)^(ThePnt.XYZ()-Pointi2);
573 gp_XYZ v3=(Pointi1-Pointi3)^(ThePnt.XYZ()-Pointi3);
574 if (v1*v2 >= 0. && v2*v3 >= 0. && v3*v1>=0.)
575 return Standard_True;
577 return Standard_False;
579 //=======================================================================
582 //=======================================================================
584 void IntPatch_Polyhedron::Dump()const
587 //=======================================================================
590 //=======================================================================
591 void IntPatch_Polyhedron::Size(Standard_Integer& nbdu,
592 Standard_Integer& nbdv) const
597 //=======================================================================
598 //function : Triangle
600 //=======================================================================
601 void IntPatch_Polyhedron::Triangle (const Standard_Integer Index,
602 Standard_Integer& P1,
603 Standard_Integer& P2,
604 Standard_Integer& P3) const
606 Standard_Integer line=1+((Index-1)/(nbdeltaV*2));
607 Standard_Integer colon=1+((Index-1)%(nbdeltaV*2));
608 Standard_Integer colpnt=(colon+1)/2;
610 // General formula = (line-1)*(nbdeltaV+1)+colpnt
612 // Position of P1 = MesXYZ(line,colpnt);
613 P1= (line-1)*(nbdeltaV+1) + colpnt;
615 // Position of P2= MesXYZ(line+1,colpnt+((colon-1)%2));
616 P2= line*(nbdeltaV+1) + colpnt+((colon-1)%2);
618 // Position of P3= MesXYZ(line+(colon%2),colpnt+1);
619 P3= (line-1+(colon%2))*(nbdeltaV+1) + colpnt + 1;
620 //-- printf("\nTriangle %4d P1:%4d P2:%4d P3:%4d",Index,P1,P2,P3);
622 //=======================================================================
624 //=======================================================================
625 const gp_Pnt& IntPatch_Polyhedron::Point( const Standard_Integer Index
627 ,Standard_Real& V) const
629 gp_Pnt *CMyPnts = (gp_Pnt *)C_MyPnts;
630 Standard_Real *CMyU = (Standard_Real *)C_MyU;
631 Standard_Real *CMyV = (Standard_Real *)C_MyV;
634 return CMyPnts[Index];
636 //=======================================================================
638 //=======================================================================
639 const gp_Pnt& IntPatch_Polyhedron::Point(const Standard_Integer Index) const {
640 gp_Pnt *CMyPnts = (gp_Pnt *)C_MyPnts;
641 return CMyPnts[Index];
644 //=======================================================================
646 //=======================================================================
647 void IntPatch_Polyhedron::Point (const gp_Pnt& /*p*/,
648 const Standard_Integer /*lig*/,
649 const Standard_Integer /*col*/,
650 const Standard_Real /*u*/,
651 const Standard_Real /*v*/)
653 //printf("\n IntPatch_Polyhedron::Point : Ne dois pas etre appelle\n");
656 //=======================================================================
658 //=======================================================================
659 void IntPatch_Polyhedron::Point (const Standard_Integer Index, gp_Pnt& P) const
661 gp_Pnt *CMyPnts = (gp_Pnt *)C_MyPnts;
664 //=======================================================================