1 // Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 #include "GEOM_WireframeFace.h"
22 #include <vtkObjectFactory.h>
24 #include <vtkPoints.h>
25 #include <vtkCellArray.h>
27 #include <vtkPolyDataMapper.h>
28 #include <vtkPolyData.h>
29 #include <vtkInformation.h>
30 #include <vtkInformationVector.h>
32 #include <Precision.hxx>
33 #include <BRepTools.hxx>
34 #include <TopExp_Explorer.hxx>
35 #include <Geom2dHatch_Hatcher.hxx>
36 #include <Geom2dHatch_Intersector.hxx>
37 #include <TColStd_Array1OfReal.hxx>
38 #include <TColStd_Array1OfInteger.hxx>
41 #include <TopoDS_Edge.hxx>
42 #include <BRep_Tool.hxx>
43 #include <Geom2d_TrimmedCurve.hxx>
44 #include <Geom2d_Line.hxx>
45 #include <gp_Dir2d.hxx>
46 #include <gp_Pnt2d.hxx>
48 #include <Geom2dHatch_Hatcher.hxx>
49 #include <HatchGen_Domain.hxx>
51 #include <Adaptor3d_HCurve.hxx>
53 vtkStandardNewMacro(GEOM_WireframeFace);
55 GEOM_WireframeFace::GEOM_WireframeFace():
61 this->SetNumberOfInputPorts(0);
64 GEOM_WireframeFace::~GEOM_WireframeFace()
68 int GEOM_WireframeFace::RequestData(vtkInformation *vtkNotUsed(request),
69 vtkInformationVector **vtkNotUsed(inputVector),
70 vtkInformationVector *outputVector)
72 vtkInformation *outInfo = outputVector->GetInformationObject(0);
73 vtkPolyData *aPolyData = vtkPolyData::SafeDownCast(
74 outInfo->Get(vtkDataObject::DATA_OBJECT()));
76 aPolyData->Allocate();
77 vtkPoints* aPts = vtkPoints::New();
78 aPolyData->SetPoints(aPts);
81 TFaceSet::Iterator anIter(myFaceSet);
82 for(; anIter.More(); anIter.Next()){
83 const TopoDS_Face& aFace = anIter.Value();
84 OCC2VTK(aFace,aPolyData,aPts,NbIso,Discret);
89 void GEOM_WireframeFace::SetNbIso(const int theNb[2])
91 if ( theNb[0] == NbIso[0] && theNb[1] == NbIso[1])
100 void GEOM_WireframeFace::GetNbIso(int &theNbU,int &theNbV)
108 OCC2VTK(const TopoDS_Face& theFace,
109 vtkPolyData* thePolyData,
111 const int theNbIso[2],
112 const int theDiscret)
114 TopoDS_Face aFace = theFace;
115 aFace.Orientation(TopAbs_FORWARD);
116 CreateIso(aFace,theNbIso,theDiscret,thePolyData,thePts);
121 CreateIso(const TopoDS_Face& theFace,
122 const int theNbIso[2],
123 const int theDiscret,
124 vtkPolyData* thePolyData,
127 // Constants for iso building
128 static Standard_Real INTERSECTOR_CONFUSION = 1.e-10 ; // -8 ;
129 static Standard_Real INTERSECTOR_TANGENCY = 1.e-10 ; // -8 ;
131 static Standard_Real HATHCER_CONFUSION_2D = 1.e-8 ;
132 static Standard_Real HATHCER_CONFUSION_3D = 1.e-8 ;
135 aHatcher(Geom2dHatch_Intersector(INTERSECTOR_CONFUSION,
136 INTERSECTOR_TANGENCY),
137 HATHCER_CONFUSION_2D,
138 HATHCER_CONFUSION_3D,
142 Standard_Real anUMin, anUMax, aVMin, aVMax;
143 TColStd_Array1OfReal anUPrm(0, theNbIso[0]), aVPrm(0, theNbIso[1]);
144 TColStd_Array1OfInteger anUInd(0, theNbIso[0]), aVInd(0, theNbIso[1]);
149 //-----------------------------------------------------------------------
150 // If the Min Max bounds are infinite, there are bounded to Infinite
152 //-----------------------------------------------------------------------
153 BRepTools::UVBounds(theFace, anUMin, anUMax, aVMin, aVMax) ;
154 Standard_Boolean InfiniteUMin = Precision::IsNegativeInfinite (anUMin) ;
155 Standard_Boolean InfiniteUMax = Precision::IsPositiveInfinite (anUMax) ;
156 Standard_Boolean InfiniteVMin = Precision::IsNegativeInfinite (aVMin) ;
157 Standard_Boolean InfiniteVMax = Precision::IsPositiveInfinite (aVMax) ;
159 static float VTKINFINITE = 1.0E38;
160 if(InfiniteUMin && InfiniteUMax){
161 anUMin = - VTKINFINITE ;
162 anUMax = VTKINFINITE ;
163 }else if(InfiniteUMin){
164 anUMin = anUMax - VTKINFINITE ;
165 }else if(InfiniteUMax){
166 anUMax = anUMin + VTKINFINITE ;
169 if(InfiniteVMin && InfiniteVMax){
170 aVMin = - VTKINFINITE ;
171 aVMax = VTKINFINITE ;
172 }else if(InfiniteVMin){
173 aVMin = aVMax - VTKINFINITE ;
174 }else if(InfiniteVMax){
175 aVMax = aVMin + VTKINFINITE ;
178 //-----------------------------------------------------------------------
179 // Retreiving the edges and loading them into the hatcher.
180 //-----------------------------------------------------------------------
181 TopExp_Explorer ExpEdges(theFace, TopAbs_EDGE);
182 for(; ExpEdges.More(); ExpEdges.Next()){
183 const TopoDS_Edge& anEdge = TopoDS::Edge(ExpEdges.Current());
184 Standard_Real U1, U2 ;
185 const Handle(Geom2d_Curve) PCurve =
186 BRep_Tool::CurveOnSurface(anEdge, theFace, U1, U2) ;
188 if(PCurve.IsNull() || U1 == U2)
191 //-- Test if a TrimmedCurve is necessary
192 if(Abs(PCurve->FirstParameter()-U1) <= Precision::PConfusion() &&
193 Abs(PCurve->LastParameter()-U2) <= Precision::PConfusion())
195 aHatcher.AddElement(PCurve, anEdge.Orientation()) ;
197 if(!PCurve->IsPeriodic()){
198 Handle(Geom2d_TrimmedCurve) TrimPCurve =
199 Handle(Geom2d_TrimmedCurve)::DownCast(PCurve);
200 if(!TrimPCurve.IsNull()){
201 Handle_Geom2d_Curve aBasisCurve = TrimPCurve->BasisCurve();
202 if(aBasisCurve->FirstParameter()-U1 > Precision::PConfusion() ||
203 U2-aBasisCurve->LastParameter() > Precision::PConfusion())
205 aHatcher.AddElement(PCurve, anEdge.Orientation()) ;
209 if(PCurve->FirstParameter()-U1 > Precision::PConfusion()){
210 U1=PCurve->FirstParameter();
212 if(U2-PCurve->LastParameter() > Precision::PConfusion()){
213 U2=PCurve->LastParameter();
217 Handle(Geom2d_TrimmedCurve) TrimPCurve =
218 new Geom2d_TrimmedCurve(PCurve, U1, U2);
219 aHatcher.AddElement(TrimPCurve, anEdge.Orientation());
224 //-----------------------------------------------------------------------
225 // Loading and trimming the hatchings.
226 //-----------------------------------------------------------------------
227 Standard_Integer IIso;
228 Standard_Real DeltaU = Abs(anUMax - anUMin) ;
229 Standard_Real DeltaV = Abs(aVMax - aVMin) ;
230 Standard_Real confusion = Min(DeltaU, DeltaV) * HATHCER_CONFUSION_3D ;
231 aHatcher.Confusion3d (confusion) ;
234 Standard_Real StepU = DeltaU / (Standard_Real)theNbIso[0];
235 if(StepU > confusion){
236 Standard_Real UPrm = anUMin + StepU / 2.;
237 gp_Dir2d Dir(0., 1.) ;
238 for(IIso = 1 ; IIso <= theNbIso[0] ; IIso++) {
239 anUPrm(IIso) = UPrm ;
240 gp_Pnt2d Ori (UPrm, 0.) ;
241 Geom2dAdaptor_Curve HCur (new Geom2d_Line (Ori, Dir)) ;
242 anUInd(IIso) = aHatcher.AddHatching (HCur) ;
249 Standard_Real StepV = DeltaV / (Standard_Real) theNbIso[1] ;
250 if(StepV > confusion){
251 Standard_Real VPrm = aVMin + StepV / 2.;
252 gp_Dir2d Dir(1., 0.);
253 for(IIso = 1 ; IIso <= theNbIso[1] ; IIso++){
255 gp_Pnt2d Ori (0., VPrm);
256 Geom2dAdaptor_Curve HCur(new Geom2d_Line (Ori, Dir));
257 aVInd(IIso) = aHatcher.AddHatching (HCur) ;
263 //-----------------------------------------------------------------------
265 //-----------------------------------------------------------------------
268 Standard_Integer aNbDom = 0 ; // for debug purpose
269 Standard_Integer Index ;
271 for(IIso = 1 ; IIso <= theNbIso[0] ; IIso++){
272 Index = anUInd(IIso) ;
274 if(aHatcher.TrimDone(Index) && !aHatcher.TrimFailed(Index)){
275 aHatcher.ComputeDomains(Index);
276 if(aHatcher.IsDone (Index))
277 aNbDom = aHatcher.NbDomains (Index);
282 for(IIso = 1 ; IIso <= theNbIso[1] ; IIso++){
285 if(aHatcher.TrimDone (Index) && !aHatcher.TrimFailed(Index)){
286 aHatcher.ComputeDomains (Index);
287 if(aHatcher.IsDone (Index))
288 aNbDom = aHatcher.NbDomains (Index);
293 //-----------------------------------------------------------------------
294 // Push iso lines in vtk kernel
295 //-----------------------------------------------------------------------
296 for(Standard_Integer UIso = anUPrm.Lower() ; UIso <= anUPrm.Upper(); UIso++){
297 Standard_Integer UInd = anUInd.Value(UIso);
299 Standard_Real UPrm = anUPrm.Value(UIso);
300 if(aHatcher.IsDone(UInd)){
301 Standard_Integer NbDom = aHatcher.NbDomains(UInd);
302 for(Standard_Integer IDom = 1 ; IDom <= NbDom ; IDom++){
303 const HatchGen_Domain& Dom = aHatcher.Domain(UInd, IDom) ;
304 Standard_Real V1 = Dom.HasFirstPoint()? Dom.FirstPoint().Parameter(): aVMin - VTKINFINITE;
305 Standard_Real V2 = Dom.HasSecondPoint()? Dom.SecondPoint().Parameter(): aVMax + VTKINFINITE;
306 CreateIso_(theFace, GeomAbs_IsoU, UPrm, V1, V2, theDiscret, thePolyData, thePts);
312 for(Standard_Integer VIso = aVPrm.Lower() ; VIso <= aVPrm.Upper(); VIso++){
313 Standard_Integer VInd = aVInd.Value(VIso);
315 Standard_Real VPrm = aVPrm.Value(VIso);
316 if(aHatcher.IsDone (VInd)){
317 Standard_Integer NbDom = aHatcher.NbDomains(VInd);
318 for (Standard_Integer IDom = 1 ; IDom <= NbDom ; IDom++){
319 const HatchGen_Domain& Dom = aHatcher.Domain(VInd, IDom);
320 Standard_Real U1 = Dom.HasFirstPoint()? Dom.FirstPoint().Parameter(): aVMin - VTKINFINITE;
321 Standard_Real U2 = Dom.HasSecondPoint()? Dom.SecondPoint().Parameter(): aVMax + VTKINFINITE;
322 CreateIso_(theFace, GeomAbs_IsoV, VPrm, U1, U2, theDiscret, thePolyData, thePts);
333 CreateIso_(const TopoDS_Face& theFace,
334 GeomAbs_IsoType theIsoType,
338 const int theDiscret,
339 vtkPolyData* thePolyData,
342 Standard_Real U1, U2, V1, V2, stepU=0., stepV=0.;
346 TopLoc_Location aLoc;
347 const Handle(Geom_Surface)& S = BRep_Tool::Surface(theFace,aLoc);
350 BRepAdaptor_Surface S(theFace,Standard_False);
352 GeomAbs_SurfaceType SurfType = S.GetType();
354 GeomAbs_CurveType CurvType = GeomAbs_OtherCurve;
356 Standard_Integer Intrv, nbIntv;
357 Standard_Integer nbUIntv = S.NbUIntervals(GeomAbs_CN);
358 Standard_Integer nbVIntv = S.NbVIntervals(GeomAbs_CN);
359 TColStd_Array1OfReal TI(1,Max(nbUIntv, nbVIntv)+1);
361 if(theIsoType == GeomAbs_IsoU){
362 S.VIntervals(TI, GeomAbs_CN);
370 S.UIntervals(TI, GeomAbs_CN);
382 for(Intrv = 1; Intrv <= nbIntv; Intrv++){
383 if(TI(Intrv) <= T1 && TI(Intrv + 1) <= T1)
385 if(TI(Intrv) >= T2 && TI(Intrv + 1) >= T2)
387 if(theIsoType == GeomAbs_IsoU){
388 V1 = Max(T1, TI(Intrv));
389 V2 = Min(T2, TI(Intrv + 1));
390 stepV = (V2 - V1) / theDiscret;
392 U1 = Max(T1, TI(Intrv));
393 U2 = Min(T2, TI(Intrv + 1));
394 stepU = (U2 - U1) / theDiscret;
400 case GeomAbs_Cylinder :
402 if(theIsoType == GeomAbs_IsoV){
403 for(j = 1; j < theDiscret; j++){
407 DrawTo(P,thePolyData,thePts);
411 case GeomAbs_Sphere :
413 case GeomAbs_OffsetSurface :
414 case GeomAbs_OtherSurface :
415 for(j = 1; j < theDiscret; j++){
419 DrawTo(P,thePolyData,thePts);
422 case GeomAbs_BezierSurface :
423 case GeomAbs_BSplineSurface :
424 for(j = 1; j <= theDiscret/2; j++){
425 Standard_Real aStep = (theIsoType == GeomAbs_IsoV) ? stepU*2. : stepV*2.;
426 CreateIso__(S, theIsoType, U1, V1, aStep, thePolyData, thePts);
431 case GeomAbs_SurfaceOfExtrusion :
432 case GeomAbs_SurfaceOfRevolution :
433 if((theIsoType == GeomAbs_IsoV && SurfType == GeomAbs_SurfaceOfRevolution) ||
434 (theIsoType == GeomAbs_IsoU && SurfType == GeomAbs_SurfaceOfExtrusion))
436 if(SurfType == GeomAbs_SurfaceOfExtrusion)
438 for(j = 1; j < theDiscret; j++){
442 DrawTo(P,thePolyData,thePts);
445 CurvType = (S.BasisCurve())->GetType();
449 case GeomAbs_Circle :
450 case GeomAbs_Ellipse :
451 for (j = 1; j < theDiscret; j++) {
455 DrawTo(P,thePolyData,thePts);
458 case GeomAbs_Parabola :
459 case GeomAbs_Hyperbola :
460 case GeomAbs_BezierCurve :
461 case GeomAbs_BSplineCurve :
462 case GeomAbs_OtherCurve :
463 for(j = 1; j <= theDiscret/2; j++){
464 Standard_Real aStep = (theIsoType == GeomAbs_IsoV) ? stepU*2. : stepV*2.;
465 CreateIso__(S, theIsoType, U1, V1, aStep, thePolyData, thePts);
475 DrawTo(P,thePolyData,thePts);
484 CreateIso__(const BRepAdaptor_Surface& theSurface,
485 GeomAbs_IsoType theIsoType,
488 Standard_Real theStep,
489 vtkPolyData* thePolyData,
493 if (theIsoType == GeomAbs_IsoU) {
494 theSurface.D0(theU, theV, Pl);
495 theSurface.D0(theU, theV + theStep/2., Pm);
496 theSurface.D0(theU, theV + theStep, Pr);
498 theSurface.D0(theU, theV, Pl);
499 theSurface.D0(theU + theStep/2., theV, Pm);
500 theSurface.D0(theU + theStep, theV, Pr);
503 static Standard_Real ISO_RATIO = 1.001;
504 if (Pm.Distance(Pl) + Pm.Distance(Pr) <= ISO_RATIO*Pl.Distance(Pr)) {
505 DrawTo(Pr,thePolyData,thePts);
507 if (theIsoType == GeomAbs_IsoU) {
508 CreateIso__(theSurface, theIsoType, theU, theV, theStep/2, thePolyData, thePts);
509 Standard_Real aLocalV = theV + theStep/2 ;
510 CreateIso__(theSurface, theIsoType, theU, aLocalV , theStep/2, thePolyData, thePts);
512 CreateIso__(theSurface, theIsoType, theU, theV, theStep/2, thePolyData, thePts);
513 Standard_Real aLocalU = theU + theStep/2 ;
514 CreateIso__(theSurface, theIsoType, aLocalU , theV, theStep/2, thePolyData, thePts);