1 // Created on: 1991-07-04
2 // Created by: Christophe MARION
3 // Copyright (c) 1991-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
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.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16 
17 #include <DBRep_DrawableShape.hxx>
18 
19 #include <Adaptor3d_Curve.hxx>
20 #include <BRep_Tool.hxx>
21 #include <BRepAdaptor_Curve.hxx>
22 #include <BRepAdaptor_Surface.hxx>
23 #include <BRepMesh_IncrementalMesh.hxx>
24 #include <BRepTools.hxx>
25 #include <BRepTools_ShapeSet.hxx>
26 #include <DBRep.hxx>
27 #include <DBRep_Edge.hxx>
28 #include <DBRep_Face.hxx>
29 #include <DBRep_HideData.hxx>
30 #include <DBRep_IsoBuilder.hxx>
31 #include <DBRep_ListIteratorOfListOfEdge.hxx>
32 #include <DBRep_ListIteratorOfListOfFace.hxx>
33 #include <DBRep_ListIteratorOfListOfHideData.hxx>
34 #include <Draw_Appli.hxx>
35 #include <Draw_Color.hxx>
36 #include <Draw_Display.hxx>
37 #include <Draw_ProgressIndicator.hxx>
38 #include <Geom_BSplineCurve.hxx>
39 #include <Geom_BSplineSurface.hxx>
40 #include <GeomAdaptor_Surface.hxx>
41 #include <gp_Lin2d.hxx>
42 #include <gp_Trsf.hxx>
43 #include <Message_ProgressIndicator.hxx>
44 #include <HLRBRep.hxx>
45 #include <Poly_Connect.hxx>
46 #include <Poly_Polygon3D.hxx>
47 #include <Poly_PolygonOnTriangulation.hxx>
48 #include <Poly_Triangulation.hxx>
49 #include <Precision.hxx>
50 #include <Standard_DomainError.hxx>
51 #include <Standard_Type.hxx>
52 #include <TColgp_HArray1OfPnt.hxx>
53 #include <TColStd_DataMapIteratorOfDataMapOfIntegerInteger.hxx>
54 #include <TColStd_DataMapOfIntegerInteger.hxx>
55 #include <TColStd_HArray1OfInteger.hxx>
56 #include <TopExp.hxx>
57 #include <TopExp_Explorer.hxx>
58 #include <TopoDS.hxx>
59 #include <TopoDS_Edge.hxx>
60 #include <TopoDS_Face.hxx>
61 #include <TopoDS_Shape.hxx>
62 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
63 #include <TopTools_ListOfShape.hxx>
64 
65 IMPLEMENT_STANDARD_RTTIEXT(DBRep_DrawableShape,Draw_Drawable3D)
66 
67 static Standard_Real IsoRatio = 1.001;
68 
69 static Standard_Integer MaxPlotCount = 5; // To avoid huge recursive calls in
70 static Standard_Integer PlotCount = 0;    // PlotEdge and PlotIso for cases of "bad"
71                                           // curves and surfaces
72                                           // Set PlotCount = 0 before first call of
73                                           // PlotEdge or PlotIso
74 static TopoDS_Shape  pickshape;
75 static Standard_Real upick,vpick;
76 #ifdef _WIN32
77 extern Draw_Viewer dout;
78 #endif
79 
80 //=======================================================================
81 //function : DBRep_DrawableShape
82 //purpose  : constructor
83 //=======================================================================
84 
DBRep_DrawableShape(const TopoDS_Shape & aShape,const Draw_Color & FreeCol,const Draw_Color & ConnCol,const Draw_Color & EdgeCol,const Draw_Color & IsosCol,const Standard_Real size,const Standard_Integer nbisos,const Standard_Integer discret)85 DBRep_DrawableShape::DBRep_DrawableShape
86   (const TopoDS_Shape& aShape,
87    const Draw_Color& FreeCol,
88    const Draw_Color& ConnCol,
89    const Draw_Color& EdgeCol,
90    const Draw_Color& IsosCol,
91    const Standard_Real size,
92    const Standard_Integer nbisos,
93    const Standard_Integer discret) :
94   mySize(size),
95   myDiscret(discret),
96   myFreeCol(FreeCol),
97   myConnCol(ConnCol),
98   myEdgeCol(EdgeCol),
99   myIsosCol(IsosCol),
100   myNbIsos(nbisos),
101   myDispOr(Standard_False),
102   mytriangulations(Standard_False),
103   mypolygons(Standard_False),
104   myHLR(Standard_False),
105   myRg1(Standard_False),
106   myRgN(Standard_False),
107   myHid(Standard_False)
108 {
109   myShape = aShape;
110 }
111 
112 //=======================================================================
113 //function : updateDisplayData
114 //purpose  :
115 //=======================================================================
116 
updateDisplayData() const117 void DBRep_DrawableShape::updateDisplayData () const
118 {
119   myFaces.Clear();
120   myEdges.Clear();
121 
122   if (myShape.IsNull())
123     return;
124 
125   //==============================================================
126   // Process the faces
127   //==============================================================
128 
129   TopExp_Explorer ExpFace;
130   TopLoc_Location l;
131 
132   for (ExpFace.Init (myShape,TopAbs_FACE);
133        ExpFace.More();
134        ExpFace.Next()) {
135     TopoDS_Face TopologicalFace = TopoDS::Face (ExpFace.Current());
136     if(myNbIsos != 0) {
137         const Handle(Geom_Surface)& S =
138 	  BRep_Tool::Surface(TopologicalFace,l);
139       if (!S.IsNull()) {
140 	TopologicalFace.Orientation (TopAbs_FORWARD) ;
141 	DBRep_IsoBuilder IsoBuild (TopologicalFace, mySize, myNbIsos) ;
142 	myFaces.Append(new DBRep_Face (TopologicalFace,
143 				       IsoBuild.NbDomains(),
144 				       myIsosCol)) ;
145 	IsoBuild.LoadIsos (myFaces.Last()) ;
146       }
147       else myFaces.Append(new DBRep_Face(TopologicalFace,0, myEdgeCol));
148     }
149     else myFaces.Append(new DBRep_Face(TopologicalFace,0, myEdgeCol));
150   }
151 
152   //==============================================================
153   // process a 3D edge
154   //==============================================================
155 
156   TopTools_IndexedDataMapOfShapeListOfShape edgemap;
157   TopExp::MapShapesAndAncestors(myShape,TopAbs_EDGE,TopAbs_FACE,edgemap);
158   Standard_Integer iedge;
159 
160   for (iedge = 1; iedge <= edgemap.Extent(); iedge++) {
161 
162     const TopoDS_Edge& theEdge = TopoDS::Edge(edgemap.FindKey(iedge));
163 
164     // skip degenerated edges
165     if (BRep_Tool::Degenerated(theEdge)) continue;
166 
167     // compute the number of faces
168     Standard_Integer nbf = edgemap(iedge).Extent();
169 
170     Draw_Color EdgeColor;
171 
172     switch (nbf) {
173 
174     case 0 :
175       EdgeColor = myEdgeCol;    // isolated edge
176       break;
177 
178     case 1 :
179       EdgeColor = myFreeCol;    // edge in only one face
180       break;
181 
182       default :
183 	EdgeColor = myConnCol;    // edge shared by at least two faces
184     }
185 
186     myEdges.Append(new DBRep_Edge (theEdge,EdgeColor));
187   }
188 }
189 
190 
191 //=======================================================================
192 //function : ChangeNbIsos
193 //purpose  : Changes the number of isoparametric curves in a shape.
194 //=======================================================================
195 
ChangeNbIsos(const Standard_Integer NbIsos)196 void  DBRep_DrawableShape::ChangeNbIsos (const Standard_Integer NbIsos)
197 {
198   myFaces.Clear();
199   myNbIsos = NbIsos ;
200   TopExp_Explorer ExpFace;
201   TopLoc_Location l;
202 
203   for (ExpFace.Init (myShape, TopAbs_FACE);
204        ExpFace.More();
205        ExpFace.Next()) {
206     TopoDS_Face TopologicalFace = TopoDS::Face (ExpFace.Current());
207     const Handle(Geom_Surface)& S =
208       BRep_Tool::Surface(TopologicalFace,l);
209     if (myNbIsos != 0) {
210       if (!S.IsNull()) {
211 	TopologicalFace.Orientation (TopAbs_FORWARD) ;
212 	DBRep_IsoBuilder IsoBuild (TopologicalFace, mySize, myNbIsos) ;
213 	myFaces.Append
214 	  (new DBRep_Face
215 	   (TopologicalFace, IsoBuild.NbDomains(), myIsosCol)) ;
216 	IsoBuild.LoadIsos (myFaces.Last()) ;
217       }
218       else myFaces.Append(new DBRep_Face(TopologicalFace,0, myEdgeCol));
219     }
220     else  myFaces.Append(new DBRep_Face(TopologicalFace,0, myEdgeCol));
221   }
222 }
223 
224 //=======================================================================
225 // Function : NbIsos
226 // Purpose  : Returns the number of isoparametric curves in a shape.
227 //=======================================================================
228 
NbIsos() const229 Standard_Integer DBRep_DrawableShape::NbIsos () const
230 {
231   return myNbIsos ;
232 }
233 
234 //=======================================================================
235 // Function : Discret
236 // Purpose  :
237 //=======================================================================
238 
Discret() const239 Standard_Integer DBRep_DrawableShape::Discret () const
240 {
241   return myDiscret ;
242 }
243 
244 Standard_EXPORT Draw_Color DBRep_ColorOrientation (const TopAbs_Orientation Or);
245 
246 
PlotIso(Draw_Display & dis,Handle (DBRep_Face)& F,BRepAdaptor_Surface & S,GeomAbs_IsoType T,Standard_Real & U,Standard_Real & V,Standard_Real Step,Standard_Boolean & halt)247 static void PlotIso (Draw_Display& dis,
248 			 Handle(DBRep_Face)& F,
249 			 BRepAdaptor_Surface& S,
250 			 GeomAbs_IsoType T,
251 			 Standard_Real& U,
252 			 Standard_Real& V,
253 			 Standard_Real Step,
254 			 Standard_Boolean& halt)
255 {
256 
257   ++PlotCount;
258 
259   gp_Pnt Pl, Pr, Pm;
260 
261    if (T == GeomAbs_IsoU) {
262     S.D0(U, V, Pl);
263     S.D0(U, V + Step/2., Pm);
264     S.D0(U, V + Step, Pr);
265   } else {
266     S.D0(U, V, Pl);
267     S.D0(U + Step/2., V, Pm);
268     S.D0(U + Step, V, Pr);
269   }
270 
271   if (PlotCount > MaxPlotCount) {
272     dis.DrawTo(Pr);
273     if (dis.HasPicked()) {
274       pickshape = F->Face();
275       upick = (T == GeomAbs_IsoU) ? U : U + Step;
276       vpick = (T == GeomAbs_IsoU) ? V + Step : V;
277       halt = Standard_True;
278     };
279     return;
280   }
281 
282   if (Pm.Distance(Pl) + Pm.Distance(Pr) <= IsoRatio*Pl.Distance(Pr)) {
283     dis.DrawTo(Pr);
284     if (dis.HasPicked()) {
285       pickshape = F->Face();
286       upick = (T == GeomAbs_IsoU) ? U : U + Step;
287       vpick = (T == GeomAbs_IsoU) ? V + Step : V;
288       halt = Standard_True;
289     };
290   } else
291      if (T == GeomAbs_IsoU) {
292        PlotIso (dis, F, S, T, U, V, Step/2, halt);
293        Standard_Real aLocalV = V + Step/2 ;
294        PlotIso (dis, F, S, T, U, aLocalV , Step/2, halt);
295      } else {
296        PlotIso (dis, F, S, T, U, V, Step/2, halt);
297        Standard_Real aLocalU = U + Step/2 ;
298        PlotIso (dis, F, S, T, aLocalU , V, Step/2, halt);
299      }
300 }
301 
302 
PlotEdge(Draw_Display & dis,Handle (DBRep_Edge)& E,const Adaptor3d_Curve & C,Standard_Real & f,Standard_Real step,Standard_Boolean & halt)303 static void PlotEdge (Draw_Display& dis,
304 		      Handle(DBRep_Edge)& E,
305 		      const Adaptor3d_Curve& C,
306 		      Standard_Real& f,
307 		      Standard_Real step,
308 		      Standard_Boolean& halt)
309 {
310 
311   ++PlotCount;
312 
313   gp_Pnt Pl, Pr, Pm;
314 
315   C.D0(f, Pl);
316   C.D0(f + step/2., Pm);
317   C.D0(f + step, Pr);
318 
319   if (PlotCount > MaxPlotCount) {
320     dis.DrawTo(Pr);
321     if (dis.HasPicked()) {
322       pickshape = E->Edge();
323       upick = f + step;
324       vpick = 0;
325       halt = Standard_True;
326     }
327     return;
328   }
329 
330 
331   if (Pm.Distance(Pl) + Pm.Distance(Pr) <= IsoRatio*Pl.Distance(Pr)) {
332     dis.DrawTo(Pr);
333     if (dis.HasPicked()) {
334       pickshape = E->Edge();
335       upick = f + step;
336       vpick = 0;
337       halt = Standard_True;
338     };
339   } else {
340     PlotEdge (dis, E, C, f, step/2, halt);
341     Standard_Real aLocalF = f + step/2 ;
342     PlotEdge (dis, E, C, aLocalF , step/2, halt);
343   }
344 }
345 
346 //=======================================================================
347 //function : DrawOn
348 //purpose  :
349 //=======================================================================
350 
DrawOn(Draw_Display & dis) const351 void  DBRep_DrawableShape::DrawOn(Draw_Display& dis) const
352 {
353   Standard_Boolean halt = Standard_False;
354 
355   if (myShape.IsNull()) {
356     dis.SetColor(myConnCol);
357     dis.DrawString(gp_Pnt(0,0,0),"Null Shape");
358     return;
359   }
360 
361   if (myFaces.IsEmpty() || myEdges.IsEmpty())
362     updateDisplayData();
363 
364   // hidden lines
365   if (myHLR) {
366     DBRep_DrawableShape* p = (DBRep_DrawableShape*) this;
367     p->DisplayHiddenLines(dis);
368     return;
369   }
370 
371   GeomAbs_IsoType T;
372   Standard_Real Par,T1,T2;
373   Standard_Real U1,U2,V1,V2,stepU=0.,stepV=0.;
374 //  gp_Pnt P, P1;
375   gp_Pnt P;
376   Standard_Integer i,j;
377 
378   // Faces
379   Handle(Poly_Triangulation) Tr;
380   TopLoc_Location aTempLoc;
381   TopLoc_Location loc;
382 
383   DBRep_ListIteratorOfListOfFace itf(myFaces);
384 
385   while (itf.More() && !halt) {
386 
387     const Handle(DBRep_Face)& F = itf.Value();
388     dis.SetColor(F->Color());
389 
390     Handle(Geom_Surface) aSurf = BRep_Tool::Surface(F->Face(), aTempLoc);
391 
392     if (!aSurf.IsNull()) {
393 
394       Standard_Boolean restriction = Standard_False;
395       if(aSurf->IsUPeriodic() || aSurf->IsVPeriodic()) {
396         Standard_Real SU1 = 0., SU2 = 0., SV1 = 0., SV2 = 0.;
397         Standard_Real FU1 = 0., FU2 = 0., FV1 = 0., FV2 = 0.;
398         aSurf->Bounds(SU1,SU2,SV1,SV2);
399         BRepTools::UVBounds (F->Face(),FU1,FU2,FV1,FV2);
400         if(aSurf->IsUPeriodic()) {
401           if(FU1 < SU1 || FU1 > SU2)
402             restriction = Standard_True;
403           if(!restriction && (FU2 < SU1 || FU2 > SU2))
404             restriction = Standard_True;
405         }
406         if(!restriction && aSurf->IsVPeriodic()) {
407           if(FV1 < SV1 || FV1 > SV2)
408             restriction = Standard_True;
409           if(!restriction && (FV2 < SV1 || FV2 > SV2))
410             restriction = Standard_True;
411         }
412         Standard_Boolean  zeroS = (fabs(SU2-SU1) <= 1.e-9 || fabs(SV2-SV1) <= 1.e-9);
413         Standard_Boolean  zeroF = (fabs(FU2-FU1) <= 1.e-9 || fabs(FV2-FV1) <= 1.e-9);
414         if(restriction && (zeroS || zeroF))
415           restriction = Standard_False;
416         if(restriction && (FU1 >= FU2 || FV1 >= FV2))
417           restriction = Standard_False;
418         if(restriction && (fabs(FU2-FU1) > 4.1e+100 || fabs(FV2-FV1) > 4.1e+100))
419           restriction = Standard_False;
420       }
421 
422       BRepAdaptor_Surface S(F->Face(),restriction);
423 
424       //BRepAdaptor_Surface S(F->Face(),Standard_False);
425 
426       GeomAbs_SurfaceType SurfType = S.GetType();
427 
428 // If the type of the surface is GeomAbs_SurfaceOfExtrusion or GeomAbs_SurfaceOfRevolution
429 #ifdef OCCT_DEBUG
430       GeomAbs_CurveType CurvType;
431 #else
432       GeomAbs_CurveType CurvType = GeomAbs_OtherCurve;
433 #endif
434 
435       Standard_Integer N = F->NbIsos();
436 
437       Standard_Integer Intrv, nbIntv;
438       Standard_Integer nbUIntv = S.NbUIntervals(GeomAbs_CN);
439       Standard_Integer nbVIntv = S.NbVIntervals(GeomAbs_CN);
440       TColStd_Array1OfReal TI(1,Max(nbUIntv, nbVIntv)+1);
441 
442       for (i = 1; i <= N; i++) {
443 
444 	F->GetIso(i,T,Par,T1,T2);
445 	if (T == GeomAbs_IsoU) {
446 	  S.VIntervals(TI, GeomAbs_CN);
447 	  V1 = Max(T1, TI(1));
448 	  V2 = Min(T2, TI(2));
449 	  U1 = Par;
450 	  U2 = Par;
451 	  stepU = 0;
452 	  nbIntv = nbVIntv;
453 	}
454 	else {
455 	  S.UIntervals(TI, GeomAbs_CN);
456 	  U1 = Max(T1, TI(1));
457 	  U2 = Min(T2, TI(2));
458 	  V1 = Par;
459 	  V2 = Par;
460 	  stepV = 0;
461 	  nbIntv = nbUIntv;
462 	}
463 
464 	S.D0(U1,V1,P);
465 	dis.MoveTo(P);
466 
467  	for (Intrv = 1; Intrv <= nbIntv; Intrv++) {
468 
469 	  if (TI(Intrv) <= T1 && TI(Intrv + 1) <= T1)
470 	    continue;
471 	  if (TI(Intrv) >= T2 && TI(Intrv + 1) >= T2)
472  	    continue;
473 	  if (T == GeomAbs_IsoU) {
474 	    V1 = Max(T1, TI(Intrv));
475 	    V2 = Min(T2, TI(Intrv + 1));
476 	    stepV = (V2 - V1) / myDiscret;
477 	  }
478 	  else {
479 	    U1 = Max(T1, TI(Intrv));
480 	    U2 = Min(T2, TI(Intrv + 1));
481 	    stepU = (U2 - U1) / myDiscret;
482 	  }
483 
484 	  switch (SurfType) {
485 //-------------GeomAbs_Plane---------------
486 	  case GeomAbs_Plane :
487 	    break;
488 //----GeomAbs_Cylinder   GeomAbs_Cone------
489 	  case GeomAbs_Cylinder :
490 	  case GeomAbs_Cone :
491 	    if (T == GeomAbs_IsoV) {
492 	      for (j = 1; j < myDiscret; j++) {
493 		U1 += stepU;
494 		V1 += stepV;
495 		S.D0(U1,V1,P);
496 		dis.DrawTo(P);
497 		if (dis.HasPicked()) {
498 		  pickshape = F->Face();
499 		  upick = U1;
500 		  vpick = V1;
501 		  halt = Standard_True;
502 		}
503 	      }
504 	    }
505 	    break;
506 //---GeomAbs_Sphere   GeomAbs_Torus--------
507 //GeomAbs_BezierSurface GeomAbs_BezierSurface
508 	  case GeomAbs_Sphere :
509 	  case GeomAbs_Torus :
510 	  case GeomAbs_OffsetSurface :
511 	  case GeomAbs_OtherSurface :
512 	    for (j = 1; j < myDiscret; j++) {
513 	      U1 += stepU;
514 	      V1 += stepV;
515 	      S.D0(U1,V1,P);
516 	      dis.DrawTo(P);
517 	      if (dis.HasPicked()) {
518 		pickshape = F->Face();
519 		upick = U1;
520 		vpick = V1;
521 		halt = Standard_True;
522 	      }
523 	    }
524 	    break;
525 //-------------GeomAbs_BSplineSurface------
526 	  case GeomAbs_BezierSurface :
527 	  case GeomAbs_BSplineSurface :
528 	    for (j = 1; j <= myDiscret/2; j++) {
529 	      Handle(DBRep_Face) aLocalFace = F;
530 
531 	      PlotCount = 0;
532 
533 	      PlotIso (dis, aLocalFace , S, T, U1, V1, (T == GeomAbs_IsoV) ? stepU*2. : stepV*2., halt);
534 	      U1 += stepU*2.;
535 	      V1 += stepV*2.;
536 	    }
537 	    break;
538 //-------------GeomAbs_SurfaceOfExtrusion--
539 //-------------GeomAbs_SurfaceOfRevolution-
540 	  case GeomAbs_SurfaceOfExtrusion :
541 	  case GeomAbs_SurfaceOfRevolution :
542 	    if ((T == GeomAbs_IsoV && SurfType == GeomAbs_SurfaceOfRevolution) ||
543 		(T == GeomAbs_IsoU && SurfType == GeomAbs_SurfaceOfExtrusion)) {
544 	      if (SurfType == GeomAbs_SurfaceOfExtrusion) break;
545 	      for (j = 1; j < myDiscret; j++) {
546 		U1 += stepU;
547 		V1 += stepV;
548 		S.D0(U1,V1,P);
549 		dis.DrawTo(P);
550 		if (dis.HasPicked()) {
551 		  pickshape = F->Face();
552 		  upick = U1;
553 		  vpick = V1;
554 		  halt = Standard_True;
555 		}
556 	      }
557 	    } else {
558 	      CurvType = (S.BasisCurve())->GetType();
559 	      switch (CurvType) {
560 	      case GeomAbs_Line :
561 		break;
562 	      case GeomAbs_Circle :
563 	      case GeomAbs_Ellipse :
564 		for (j = 1; j < myDiscret; j++) {
565 		  U1 += stepU;
566 		  V1 += stepV;
567 		  S.D0(U1,V1,P);
568 		  dis.DrawTo(P);
569 		  if (dis.HasPicked()) {
570 		    pickshape = F->Face();
571 		    upick = U1;
572 		    vpick = V1;
573 		    halt = Standard_True;
574 		  }
575 		}
576 		break;
577 	      case GeomAbs_Parabola :
578 	      case GeomAbs_Hyperbola :
579 	      case GeomAbs_BezierCurve :
580 	      case GeomAbs_BSplineCurve :
581 	      case GeomAbs_OffsetCurve :
582 	      case GeomAbs_OtherCurve :
583 		for (j = 1; j <= myDiscret/2; j++) {
584 		  Handle(DBRep_Face) aLocalFace = F;
585 
586 		  PlotCount = 0;
587 
588 		  PlotIso (dis, aLocalFace, S, T, U1, V1,
589 			   (T == GeomAbs_IsoV) ? stepU*2. : stepV*2., halt);
590 		  U1 += stepU*2.;
591 		  V1 += stepV*2.;
592 		}
593 		break;
594 	      }
595 	    }
596 	  }
597 	}
598 	S.D0(U2,V2,P);
599 	dis.DrawTo(P);
600 	if (dis.HasPicked()) {
601 	  pickshape = F->Face();
602 	  upick = U2;
603 	  vpick = V2;
604 	  halt = Standard_True;
605 	}
606       }
607     }
608 
609     //=====================================
610     // trace des eventuelles triangulations.
611     //=====================================
612 
613     if (aSurf.IsNull() || mytriangulations) {
614       Tr = BRep_Tool::Triangulation(F->Face(), loc);
615       if (!Tr.IsNull()) {
616 	display(Tr, loc.Transformation(), dis);
617       }
618     }
619     itf.Next();
620   }
621 
622 
623   // Edges
624   DBRep_ListIteratorOfListOfEdge ite(myEdges);
625   while (ite.More() && !halt) {
626 
627     const Handle(DBRep_Edge)& E = ite.Value();
628 
629     if(myDispOr)
630       dis.SetColor(DBRep_ColorOrientation(E->Edge().Orientation()));
631     else
632       dis.SetColor(E->Color());
633 
634     // display geometrical curve if exists.
635     Standard_Boolean isgeom = BRep_Tool::IsGeometric(E->Edge());
636     Standard_Real aCheckU1, aCheckU2;
637 
638     if (isgeom) {
639       // check the range (to report bad edges)
640       BRep_Tool::Range(E->Edge(), aCheckU1, aCheckU2);
641       if (aCheckU2 < aCheckU1) {
642 	// bad orientation
643 	std::cout << "DBRep_DrawableShape : Bad parameters on edge."<<std::endl;
644 	BRepTools::Dump(E->Edge(),std::cout);
645 	ite.Next();
646 	continue;
647       }
648 
649       if (BRep_Tool::Degenerated(E->Edge())) {
650 	ite.Next();
651  	continue;
652       }
653 
654       BRepAdaptor_Curve C(E->Edge());
655 
656       Standard_Real f = C.FirstParameter();
657       Standard_Real l = C.LastParameter();
658       if (Precision::IsNegativeInfinite(f)) {
659 	if (Precision::IsPositiveInfinite(l)) {
660 	  f = -mySize;
661 	  l = mySize;
662 	}
663 	else {
664 	  f = l - mySize;
665 	}
666       }
667       else if (Precision::IsPositiveInfinite(l)) {
668 	l = f + mySize;
669       }
670 
671       Handle(Adaptor3d_Curve) HC = C.Trim(f, l, Precision::Confusion());
672       GeomAbs_CurveType CurvType = HC->GetType();
673 
674       Standard_Integer intrv, nbintv = HC->NbIntervals(GeomAbs_CN);
675       TColStd_Array1OfReal TI(1,nbintv+1);
676       HC->Intervals(TI,GeomAbs_CN);
677 
678       HC->D0(HC->FirstParameter(), P);
679       dis.MoveTo(P);
680 
681       for (intrv = 1; intrv <= nbintv; intrv++) {
682 	Standard_Real t = TI(intrv);
683 	Standard_Real step = (TI(intrv+1) - t) / myDiscret;
684 
685 	switch (CurvType) {
686 	case GeomAbs_Line :
687 	  break;
688 	case GeomAbs_Circle :
689 	case GeomAbs_Ellipse :
690 	  for (j = 1; j < myDiscret; j++) {
691 	    t += step;
692 	    C.D0(t,P);
693 	    dis.DrawTo(P);
694 	    if (dis.HasPicked()) {
695 	      pickshape = E->Edge();
696 	      upick = t;
697 	      vpick = 0;
698 	      halt = Standard_True;
699 	    }
700 	  }
701 	  break;
702 	case GeomAbs_Parabola :
703 	case GeomAbs_Hyperbola :
704 	case GeomAbs_BezierCurve :
705 	case GeomAbs_BSplineCurve :
706 	case GeomAbs_OffsetCurve :
707 	case GeomAbs_OtherCurve :
708 	  for (j = 1; j <= myDiscret/2; j++) {
709 	    Handle(DBRep_Edge) aLocaLEdge(E);
710 	    PlotCount = 0;
711 	    PlotEdge (dis, aLocaLEdge, *HC, t, step*2., halt);
712 	    t += step*2.;
713 	  }
714 	  break;
715 	}
716       }
717 
718 	C.D0(HC->LastParameter(),P);
719 	dis.DrawTo(P);
720 	if (dis.HasPicked()) {
721 	  pickshape = E->Edge();
722 	  upick = l;
723 	  vpick = 0;
724 	  halt = Standard_True;
725 	}
726 
727       if (myDispOr) {
728 	// display an arrow at the end
729 	gp_Pnt aPnt;
730 	gp_Vec V;
731 	C.D1(l, aPnt,V);
732 	gp_Pnt2d p1,p2;
733 	dis.Project(aPnt,p1);
734   aPnt.Translate(V);
735 	dis.Project(aPnt,p2);
736 	gp_Vec2d v(p1,p2);
737 	if (v.Magnitude() > gp::Resolution()) {
738 	  Standard_Real L = 20 / dis.Zoom();
739 	  Standard_Real H = 10 / dis.Zoom();
740 	  gp_Dir2d d(v);
741 	  p2.SetCoord(p1.X() - L*d.X() - H*d.Y(), p1.Y() - L*d.Y() + H*d.X());
742 	  dis.MoveTo(p2);
743 	  p2.SetCoord(p1.X() - L*d.X() + H*d.Y(), p1.Y() - L*d.Y() - H*d.X());
744 	  dis.DrawTo(p1);
745 	  dis.DrawTo(p2);
746 	}
747 
748 //	gp_Vec tang;
749 //	C.D1(l,P,tang);
750 
751       }
752     }
753 
754     //======================================
755     // trace des representations polygonales:
756     //======================================
757 
758     if (!isgeom || mypolygons) {
759 
760       // Polygones 3d:
761       Handle(Poly_Polygon3D) Polyg = BRep_Tool::Polygon3D(E->Edge(), loc);
762       if (!Polyg.IsNull()) {
763 	const TColgp_Array1OfPnt& Points = Polyg->Nodes();
764 	Standard_Integer po;
765 	for (po = Points.Lower()+1; po <= Points.Upper(); po++) {
766 	  dis.Draw((Points.Value(po-1)).Transformed(loc),
767 		   (Points.Value(po)).Transformed(loc));
768 	  if (dis.HasPicked()) {
769 	    pickshape = E->Edge();
770 	    upick = 0;
771 	    vpick = 0;
772 	    halt = Standard_True;
773 	  }
774 	}
775       }
776       else {
777 
778 	// Polygone sur triangulation:
779 	Handle(Poly_Triangulation) PolyTr;
780 	Handle(Poly_PolygonOnTriangulation) Poly;
781 	BRep_Tool::PolygonOnTriangulation(E->Edge(), Poly, PolyTr, loc);
782 	if (!Poly.IsNull())
783 	{
784 	  const TColStd_Array1OfInteger& Indices = Poly->Nodes();
785 	  for (i=Indices.Lower()+1; i<=Indices.Upper(); i++)
786 	  {
787 	    dis.Draw (PolyTr->Node (Indices (i-1)).Transformed (loc),
788 	              PolyTr->Node (Indices (i  )).Transformed (loc));
789 	    if (dis.HasPicked())
790 	    {
791 	      pickshape = E->Edge();
792 	      upick = 0;
793 	      vpick = 0;
794 	      halt = Standard_True;
795 	    }
796 	  }
797 	}
798       }
799     }
800 
801     ite.Next();
802   }
803 
804 
805 
806 
807   //Vertices
808 
809   TopExp_Explorer exv;
810   dis.SetColor(myConnCol);
811 
812   for (exv.Init(myShape,TopAbs_VERTEX,TopAbs_EDGE);
813        exv.More() && !halt;
814        exv.Next()){
815 
816     if (myDispOr)
817       dis.SetColor(DBRep_ColorOrientation(exv.Current().Orientation()));
818     dis.DrawMarker(BRep_Tool::Pnt(TopoDS::Vertex(exv.Current())),
819 		   Draw_Losange);
820     if (dis.HasPicked()) {
821       pickshape = exv.Current();
822       upick = 0;
823       vpick = 0;
824       halt = Standard_True;
825     }
826 
827   }
828 
829 }
830 
831 //=======================================================================
832 //function : DisplayHiddenLines
833 //purpose  :
834 //=======================================================================
835 
DisplayHiddenLines(Draw_Display & dis)836 void DBRep_DrawableShape::DisplayHiddenLines(Draw_Display& dis)
837 {
838   Standard_Integer id = dis.ViewId();
839 
840   // get the projection
841   gp_Trsf T;
842   dout.GetTrsf(id,T);
843   Standard_Real focal = -1;
844   if (!strcmp(dout.GetType(id),"PERS")) focal = dout.Focal(id);
845   Standard_Real Ang,Def;
846   HLRBRep::PolyHLRAngleAndDeflection(myAng,Ang,Def);
847   IMeshTools_Parameters aMeshParams;
848   aMeshParams.Relative   = Standard_True;
849   aMeshParams.Deflection = Def;
850   aMeshParams.Angle      = Ang;
851 
852   BRepMesh_IncrementalMesh MESH(myShape, aMeshParams);
853   Standard_Boolean recompute = Standard_True;
854   // find if the view must be recomputed
855   DBRep_ListIteratorOfListOfHideData it(myHidData);
856 
857   while (it.More()) {
858     if (it.Value().ViewId() == id) {
859       // we have the view
860       // but did we rotate it
861       Standard_Real ang = it.Value().Angle();
862       recompute = !it.Value().IsSame(T,focal) || myAng != ang;
863       if (recompute)
864 	myHidData.Remove(it);
865       else {
866 	it.Value().DrawOn(dis,myRg1,myRgN,myHid,
867 			  myConnCol,myIsosCol);
868 	if (dis.HasPicked()) {
869 	  pickshape = it.Value().LastPick();
870 	  upick = 0;
871 	  vpick = 0;
872 	}
873       }
874       break;
875     }
876     it.Next();
877   }
878   // recompute the hidden lines and display them
879   if (recompute) {
880     DBRep_HideData theData;
881     myHidData.Append(theData);
882     myHidData.Last().Set(id,T,focal,myShape,myAng);
883     myHidData.Last().DrawOn(dis,myRg1,myRgN,myHid,
884 			    myConnCol,myIsosCol);
885     if (dis.HasPicked()) {
886       pickshape = myHidData.Last().LastPick();
887       upick = 0;
888       vpick = 0;
889     }
890   }
891 }
892 
893 //=======================================================================
894 //function : Shape
895 //purpose  :
896 //=======================================================================
897 
Shape() const898 TopoDS_Shape  DBRep_DrawableShape::Shape()const
899 {
900   return myShape;
901 }
902 
903 
904 //=======================================================================
905 //function : Copy
906 //purpose  :
907 //=======================================================================
908 
Handle(Draw_Drawable3D)909 Handle(Draw_Drawable3D)  DBRep_DrawableShape::Copy()const
910 {
911   Handle(DBRep_DrawableShape) D =
912     new DBRep_DrawableShape(myShape,
913 			    myFreeCol,
914 			    myConnCol,
915 			    myEdgeCol,
916 			    myIsosCol,
917 			    mySize,
918 			    myNbIsos,
919 			    myDiscret);
920   return D;
921 }
922 
923 //=======================================================================
924 //function : DisplayOrientation
925 //purpose  :
926 //=======================================================================
927 
DisplayOrientation(const Standard_Boolean D)928 void DBRep_DrawableShape::DisplayOrientation(const Standard_Boolean D)
929 {
930   myDispOr = D;
931 }
932 
933 //=======================================================================
934 //function : DisplayTriangulation
935 //purpose  :
936 //=======================================================================
937 
DisplayTriangulation(const Standard_Boolean D)938 void DBRep_DrawableShape::DisplayTriangulation(const Standard_Boolean D)
939 {
940   mytriangulations = D;
941 }
942 
943 //=======================================================================
944 //function : DisplayPolygons
945 //purpose  :
946 //=======================================================================
947 
DisplayPolygons(const Standard_Boolean D)948 void DBRep_DrawableShape::DisplayPolygons(const Standard_Boolean D)
949 {
950   mypolygons = D;
951 }
952 
953 //=======================================================================
954 //function : DisplayHLR
955 //purpose  :
956 //=======================================================================
957 
DisplayHLR(const Standard_Boolean withHLR,const Standard_Boolean withRg1,const Standard_Boolean withRgN,const Standard_Boolean withHid,const Standard_Real ang)958 void DBRep_DrawableShape::DisplayHLR(const Standard_Boolean withHLR,
959 				     const Standard_Boolean withRg1,
960 				     const Standard_Boolean withRgN,
961 				     const Standard_Boolean withHid,
962 				     const Standard_Real ang)
963 {
964   myHLR = withHLR;
965   myRg1 = withRg1;
966   myRgN = withRgN;
967   myHid = withHid;
968   myAng = ang;
969 }
970 
971 //=======================================================================
972 //function : DisplayTriangulation
973 //purpose  :
974 //=======================================================================
975 
DisplayTriangulation() const976 Standard_Boolean DBRep_DrawableShape::DisplayTriangulation() const
977 {
978   return mytriangulations;
979 }
980 
981 //=======================================================================
982 //function : DisplayPolygons
983 //purpose  :
984 //=======================================================================
985 
DisplayPolygons() const986 Standard_Boolean DBRep_DrawableShape::DisplayPolygons()const
987 {
988   return mypolygons;
989 }
990 
991 //=======================================================================
992 //function : GetDisplayHLR
993 //purpose  :
994 //=======================================================================
995 
GetDisplayHLR(Standard_Boolean & withHLR,Standard_Boolean & withRg1,Standard_Boolean & withRgN,Standard_Boolean & withHid,Standard_Real & ang) const996 void DBRep_DrawableShape::GetDisplayHLR(Standard_Boolean& withHLR,
997 					Standard_Boolean& withRg1,
998 					Standard_Boolean& withRgN,
999 					Standard_Boolean& withHid,
1000 					Standard_Real& ang) const
1001 {
1002   withHLR = myHLR;
1003   withRg1 = myRg1;
1004   withRgN = myRgN;
1005   withHid = myHid;
1006   ang     = myAng;
1007 }
1008 
1009 //=======================================================================
1010 //function : Dump
1011 //purpose  :
1012 //=======================================================================
Dump(Standard_OStream & S) const1013 void DBRep_DrawableShape::Dump (Standard_OStream& S) const
1014 {
1015   BRepTools::Dump(myShape,S);
1016 }
1017 
1018 //=======================================================================
1019 //function : Save
1020 //purpose  :
1021 //=======================================================================
Save(Standard_OStream & theStream) const1022 void DBRep_DrawableShape::Save (Standard_OStream& theStream) const
1023 {
1024   BRep_Builder aBuilder;
1025   BRepTools_ShapeSet aShapeSet (aBuilder);
1026   aShapeSet.Add (myShape);
1027   Handle(Draw_ProgressIndicator) aProgress = Draw::GetProgressBar();
1028   aShapeSet.Write (theStream, Message_ProgressIndicator::Start (aProgress));
1029   if (aProgress.IsNull() || !aProgress->UserBreak())
1030   {
1031     aShapeSet.Write (myShape, theStream);
1032   }
1033 }
1034 
1035 //=======================================================================
1036 //function : Restore
1037 //purpose  :
1038 //=======================================================================
Handle(Draw_Drawable3D)1039 Handle(Draw_Drawable3D) DBRep_DrawableShape::Restore (Standard_IStream& theStream)
1040 {
1041   const DBRep_Params& aParams = DBRep::Parameters();
1042   BRep_Builder aBuilder;
1043   BRepTools_ShapeSet aShapeSet (aBuilder);
1044   Handle(Draw_ProgressIndicator) aProgress = Draw::GetProgressBar();
1045   aShapeSet.Read (theStream, Message_ProgressIndicator::Start(aProgress));
1046   if (!aProgress.IsNull() && aProgress->UserBreak())
1047   {
1048     return Handle(Draw_Drawable3D)();
1049   }
1050 
1051   TopoDS_Shape aTopoShape;
1052   aShapeSet.Read (aTopoShape, theStream);
1053   Handle(DBRep_DrawableShape) aDrawShape = new DBRep_DrawableShape (aTopoShape,
1054                                                                     Draw_vert, Draw_jaune, Draw_rouge, Draw_bleu,
1055                                                                     aParams.Size, aParams.NbIsos, aParams.Discretization);
1056   aDrawShape->DisplayTriangulation (aParams.DispTriangles);
1057   aDrawShape->DisplayPolygons (aParams.DisplayPolygons);
1058   aDrawShape->DisplayHLR (aParams.WithHLR, aParams.WithRg1, aParams.WithRgN, aParams.WithHid, aParams.HLRAngle);
1059   return aDrawShape;
1060 }
1061 
1062 //=======================================================================
1063 //function : Whatis
1064 //purpose  :
1065 //=======================================================================
Whatis(Draw_Interpretor & s) const1066 void DBRep_DrawableShape::Whatis (Draw_Interpretor& s) const
1067 {
1068   if (myShape.IsNull())
1069   {
1070     return;
1071   }
1072 
1073   s << "shape " << TopAbs::ShapeTypeToString       (myShape.ShapeType())
1074     << " "      << TopAbs::ShapeOrientationToString(myShape.Orientation());
1075 
1076   if (myShape.Free())       s <<" Free";
1077   if (myShape.Modified())   s <<" Modified";
1078   if (myShape.Orientable()) s <<" Orientable";
1079   if (myShape.Closed())     s <<" Closed";
1080   if (myShape.Infinite())   s <<" Infinite";
1081   if (myShape.Convex())     s <<" Convex";
1082 }
1083 
1084 //=======================================================================
1085 //function : LastPick
1086 //purpose  :
1087 //=======================================================================
1088 
LastPick(TopoDS_Shape & s,Standard_Real & u,Standard_Real & v)1089 void  DBRep_DrawableShape::LastPick(TopoDS_Shape& s,
1090 				    Standard_Real& u, Standard_Real& v)
1091 {
1092   s = pickshape;
1093   u = upick;
1094   v = vpick;
1095 }
1096 
1097 
1098 
1099 //=======================================================================
1100 //function : display
1101 //purpose  :
1102 //=======================================================================
1103 
display(const Handle (Poly_Triangulation)& T,const gp_Trsf & tr,Draw_Display & dis) const1104 void  DBRep_DrawableShape::display(const Handle(Poly_Triangulation)& T,
1105 				   const gp_Trsf&                    tr,
1106 				   Draw_Display&                     dis) const
1107 {
1108     // Build the connect tool
1109   Poly_Connect pc(T);
1110 
1111   Standard_Integer i,j, nFree, nbTriangles = T->NbTriangles();
1112   Standard_Integer t[3];
1113 
1114   // count the free edges
1115   nFree = 0;
1116   for (i = 1; i <= nbTriangles; i++) {
1117     pc.Triangles(i,t[0],t[1],t[2]);
1118     for (j = 0; j < 3; j++)
1119       if (t[j] == 0) nFree++;
1120   }
1121 
1122   // allocate the arrays
1123   TColStd_Array1OfInteger Free (1, Max (1, 2 * nFree));
1124   NCollection_Vector< NCollection_Vec2<Standard_Integer> > anInternal;
1125 
1126   Standard_Integer fr = 1;
1127 
1128   Standard_Integer n[3];
1129   for (i = 1; i <= nbTriangles; i++) {
1130     pc.Triangles(i,t[0],t[1],t[2]);
1131     T->Triangle (i).Get (n[0],n[1],n[2]);
1132     for (j = 0; j < 3; j++) {
1133       Standard_Integer k = (j+1) % 3;
1134       if (t[j] == 0) {
1135 	Free(fr)   = n[j];
1136 	Free(fr+1) = n[k];
1137 	fr += 2;
1138       }
1139       // internal edge if this triangle has a lower index than the adjacent
1140       else if (i < t[j]) {
1141         anInternal.Append (NCollection_Vec2<Standard_Integer> (n[j], n[k]));
1142       }
1143     }
1144   }
1145 
1146   // Display the edges
1147 
1148   // free edges
1149   Standard_Integer nn;
1150   dis.SetColor(Draw_rouge);
1151   nn = Free.Length() / 2;
1152   for (i = 1; i <= nn; i++) {
1153     dis.Draw (T->Node (Free[2*i-1]).Transformed (tr),
1154               T->Node (Free[2*i]).Transformed (tr));
1155   }
1156 
1157   // internal edges
1158 
1159   dis.SetColor(Draw_bleu);
1160   for (NCollection_Vector< NCollection_Vec2<Standard_Integer> >::Iterator anInterIter (anInternal); anInterIter.More(); anInterIter.Next())
1161   {
1162     const Standard_Integer n1 = anInterIter.Value()[0];
1163     const Standard_Integer n2 = anInterIter.Value()[1];
1164     dis.Draw (T->Node (n1).Transformed (tr), T->Node (n2).Transformed (tr));
1165   }
1166 }
1167 
1168 //=======================================================================
1169 //function : addMeshNormals
1170 //purpose  :
1171 //=======================================================================
addMeshNormals(NCollection_Vector<std::pair<gp_Pnt,gp_Pnt>> & theNormals,const TopoDS_Face & theFace,const Standard_Real theLength)1172 Standard_Boolean DBRep_DrawableShape::addMeshNormals (NCollection_Vector<std::pair<gp_Pnt, gp_Pnt> >& theNormals,
1173                                                       const TopoDS_Face& theFace,
1174                                                       const Standard_Real theLength)
1175 {
1176   TopLoc_Location aLoc;
1177   const Handle(Poly_Triangulation)& aTriangulation = BRep_Tool::Triangulation (theFace, aLoc);
1178   const Standard_Boolean hasNormals = aTriangulation->HasNormals();
1179   if (aTriangulation.IsNull()
1180   || (!hasNormals && !aTriangulation->HasUVNodes()))
1181   {
1182     return Standard_False;
1183   }
1184 
1185   BRepAdaptor_Surface aSurface (theFace);
1186   for (Standard_Integer aNodeIter = 1; aNodeIter <= aTriangulation->NbNodes(); ++aNodeIter)
1187   {
1188     gp_Pnt aP1 = aTriangulation->Node (aNodeIter);
1189     if (!aLoc.IsIdentity())
1190     {
1191       aP1.Transform (aLoc.Transformation());
1192     }
1193 
1194     gp_Vec aNormal;
1195     if (hasNormals)
1196     {
1197       aNormal = aTriangulation->Normal (aNodeIter);
1198     }
1199     else
1200     {
1201       const gp_Pnt2d& aUVNode = aTriangulation->UVNode (aNodeIter);
1202       gp_Pnt aDummyPnt;
1203       gp_Vec aV1, aV2;
1204       aSurface.D1 (aUVNode.X(), aUVNode.Y(), aDummyPnt, aV1, aV2);
1205       aNormal = aV1.Crossed (aV2);
1206     }
1207 
1208     const Standard_Real aNormalLen = aNormal.Magnitude();
1209     if (aNormalLen > 1.e-10)
1210     {
1211       aNormal.Multiply (theLength / aNormalLen);
1212     }
1213     else
1214     {
1215       aNormal.SetCoord (aNormalLen / 2.0, 0.0, 0.0);
1216       std::cout << "Null normal at node X = " << aP1.X() << ", Y = " << aP1.Y() << ", Z = " << aP1.Z() << "\n";
1217     }
1218 
1219     const gp_Pnt aP2 = aP1.Translated (aNormal);
1220     theNormals.Append (std::pair<gp_Pnt, gp_Pnt> (aP1, aP2));
1221   }
1222   return Standard_True;
1223 }
1224 
1225 //=======================================================================
1226 //function : addMeshNormals
1227 //purpose  :
1228 //=======================================================================
addMeshNormals(NCollection_DataMap<TopoDS_Face,NCollection_Vector<std::pair<gp_Pnt,gp_Pnt>>> & theNormals,const TopoDS_Shape & theShape,const Standard_Real theLength)1229 void DBRep_DrawableShape::addMeshNormals (NCollection_DataMap<TopoDS_Face, NCollection_Vector<std::pair<gp_Pnt, gp_Pnt> > > & theNormals,
1230                                           const TopoDS_Shape& theShape,
1231                                           const Standard_Real theLength)
1232 {
1233   TopLoc_Location aLoc;
1234   for (TopExp_Explorer aFaceIt(theShape, TopAbs_FACE); aFaceIt.More(); aFaceIt.Next())
1235   {
1236     const TopoDS_Face& aFace = TopoDS::Face(aFaceIt.Current());
1237     NCollection_Vector<std::pair<gp_Pnt, gp_Pnt> >* aFaceNormals = theNormals.ChangeSeek(aFace);
1238     if (aFaceNormals == NULL)
1239     {
1240       aFaceNormals = theNormals.Bound(aFace, NCollection_Vector<std::pair<gp_Pnt, gp_Pnt> >());
1241     }
1242 
1243     addMeshNormals (*aFaceNormals, aFace, theLength);
1244   }
1245 }
1246 
1247 //=======================================================================
1248 //function : addSurfaceNormals
1249 //purpose  :
1250 //=======================================================================
addSurfaceNormals(NCollection_Vector<std::pair<gp_Pnt,gp_Pnt>> & theNormals,const TopoDS_Face & theFace,const Standard_Real theLength,const Standard_Integer theNbAlongU,const Standard_Integer theNbAlongV)1251 Standard_Boolean DBRep_DrawableShape::addSurfaceNormals (NCollection_Vector<std::pair<gp_Pnt, gp_Pnt> >& theNormals,
1252                                                          const TopoDS_Face&     theFace,
1253                                                          const Standard_Real    theLength,
1254                                                          const Standard_Integer theNbAlongU,
1255                                                          const Standard_Integer theNbAlongV)
1256 {
1257   {
1258     TopLoc_Location aLoc;
1259     const Handle(Geom_Surface)& aSurface = BRep_Tool::Surface (theFace, aLoc);
1260     if (aSurface.IsNull())
1261     {
1262       return Standard_False;
1263     }
1264   }
1265 
1266   Standard_Real aUmin = 0.0, aVmin = 0.0, aUmax = 0.0, aVmax = 0.0;
1267   BRepTools::UVBounds (theFace, aUmin, aUmax, aVmin, aVmax);
1268   const Standard_Boolean isUseMidU = (theNbAlongU == 1);
1269   const Standard_Boolean isUseMidV = (theNbAlongV == 1);
1270   const Standard_Real aDU = (aUmax - aUmin) / (isUseMidU ? 2 : (theNbAlongU - 1));
1271   const Standard_Real aDV = (aVmax - aVmin) / (isUseMidV ? 2 : (theNbAlongV - 1));
1272 
1273   BRepAdaptor_Surface aSurface (theFace);
1274   for (Standard_Integer aUIter = 0; aUIter < theNbAlongU; ++aUIter)
1275   {
1276     const Standard_Real aU = aUmin + (isUseMidU ? 1 : aUIter) * aDU;
1277     for (Standard_Integer aVIter = 0; aVIter < theNbAlongV; ++aVIter)
1278     {
1279       const Standard_Real aV = aVmin + (isUseMidV ? 1 : aVIter) * aDV;
1280 
1281       gp_Pnt aP1;
1282       gp_Vec aV1, aV2;
1283       aSurface.D1 (aU, aV, aP1, aV1, aV2);
1284 
1285       gp_Vec aVec = aV1.Crossed (aV2);
1286       Standard_Real aNormalLen = aVec.Magnitude();
1287       if (aNormalLen > 1.e-10)
1288       {
1289         aVec.Multiply (theLength / aNormalLen);
1290       }
1291       else
1292       {
1293         aVec.SetCoord (aNormalLen / 2.0, 0.0, 0.0);
1294         std::cout << "Null normal at U = " << aU << ", V = " << aV << "\n";
1295       }
1296 
1297       const gp_Pnt aP2 = aP1.Translated(aVec);
1298       theNormals.Append (std::pair<gp_Pnt, gp_Pnt> (aP1, aP2));
1299     }
1300   }
1301   return Standard_True;
1302 }
1303 
1304 //=======================================================================
1305 //function : addSurfaceNormals
1306 //purpose  :
1307 //=======================================================================
addSurfaceNormals(NCollection_DataMap<TopoDS_Face,NCollection_Vector<std::pair<gp_Pnt,gp_Pnt>>> & theNormals,const TopoDS_Shape & theShape,const Standard_Real theLength,const Standard_Integer theNbAlongU,const Standard_Integer theNbAlongV)1308 void DBRep_DrawableShape::addSurfaceNormals (NCollection_DataMap<TopoDS_Face, NCollection_Vector<std::pair<gp_Pnt, gp_Pnt> > >& theNormals,
1309                                              const TopoDS_Shape&    theShape,
1310                                              const Standard_Real    theLength,
1311                                              const Standard_Integer theNbAlongU,
1312                                              const Standard_Integer theNbAlongV)
1313 {
1314   for (TopExp_Explorer aFaceIt (theShape, TopAbs_FACE); aFaceIt.More(); aFaceIt.Next())
1315   {
1316     const TopoDS_Face& aFace = TopoDS::Face (aFaceIt.Current());
1317     NCollection_Vector<std::pair<gp_Pnt, gp_Pnt> >* aFaceNormals = theNormals.ChangeSeek (aFace);
1318     if (aFaceNormals == NULL)
1319     {
1320       aFaceNormals = theNormals.Bound (aFace, NCollection_Vector<std::pair<gp_Pnt, gp_Pnt> >());
1321     }
1322     addSurfaceNormals (*aFaceNormals, aFace, theLength, theNbAlongU, theNbAlongV);
1323   }
1324 }
1325