1 // Created on: 1995-01-05
2 // Created by: Christophe MARION
3 // Copyright (c) 1995-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 
18 #include <BRep_Builder.hxx>
19 #include <BRep_Tool.hxx>
20 #include <BRepAdaptor_Surface.hxx>
21 #include <BRepTools.hxx>
22 #include <Geom2d_Curve.hxx>
23 #include <Geom2d_Line.hxx>
24 #include <Geom2d_TrimmedCurve.hxx>
25 #include <Geom2dHatch_Hatcher.hxx>
26 #include <Geom2dHatch_Intersector.hxx>
27 #include <gp_Pnt.hxx>
28 #include <HatchGen_Domain.hxx>
29 #include <HatchGen_ErrorStatus.hxx>
30 #include <HatchGen_PointOnElement.hxx>
31 #include <HatchGen_PointOnHatching.hxx>
32 #include <HLRTopoBRep_Data.hxx>
33 #include <HLRTopoBRep_FaceIsoLiner.hxx>
34 #include <Precision.hxx>
35 #include <TColStd_Array1OfBoolean.hxx>
36 #include <TopAbs.hxx>
37 #include <TopExp.hxx>
38 #include <TopExp_Explorer.hxx>
39 #include <TopoDS.hxx>
40 #include <TopoDS_Edge.hxx>
41 #include <TopoDS_Face.hxx>
42 #include <TopoDS_Vertex.hxx>
43 #include <TopTools_Array1OfShape.hxx>
44 #include <TopTools_ListIteratorOfListOfShape.hxx>
45 
46 //#include <BRepAdaptor_Curve2d.hxx>
47 const Standard_Real IntersectorConfusion = 1.e-10;
48 const Standard_Real IntersectorTangency  = 1.e-10;
49 const Standard_Real HatcherConfusion2d   = 1.e-8;
50 const Standard_Real HatcherConfusion3d   = 1.e-8;
51 const Standard_Real Infinite = 100.;
52 
53 //=======================================================================
54 // Function : Perform
55 // Purpose  : Builds isoparametric curves with a hatcher.
56 //=======================================================================
57 
Perform(const Standard_Integer FI,const TopoDS_Face & F,HLRTopoBRep_Data & DS,const Standard_Integer nbIsos)58 void HLRTopoBRep_FaceIsoLiner::Perform (const Standard_Integer FI,
59 					const TopoDS_Face& F,
60 					HLRTopoBRep_Data& DS,
61 					const Standard_Integer nbIsos)
62 {
63   (void)FI; // avoid compiler warning
64 
65   Standard_Real UMin, UMax, VMin, VMax, U1, U2;
66   Standard_Integer ne = 0;
67   //BRep_Builder Builder;
68   TopoDS_Edge Edge;
69   TopExp_Explorer ExpEdges;
70   TopoDS_Face TF = F;
71   TF.Orientation (TopAbs_FORWARD);
72   gp_Pnt2d P;
73   gp_Pnt P1, P2;
74   TopoDS_Vertex V1U, V2U, V1V, V2V;
75 
76   Geom2dHatch_Intersector Intersector
77     (IntersectorConfusion,IntersectorTangency);
78   Geom2dHatch_Hatcher Hatcher
79     (Intersector,HatcherConfusion2d,HatcherConfusion3d,Standard_True);
80 
81   BRepTools::UVBounds (TF, UMin, UMax, VMin, VMax);
82   Standard_Boolean InfiniteUMin = Precision::IsNegativeInfinite (UMin);
83   Standard_Boolean InfiniteUMax = Precision::IsPositiveInfinite (UMax);
84   Standard_Boolean InfiniteVMin = Precision::IsNegativeInfinite (VMin);
85   Standard_Boolean InfiniteVMax = Precision::IsPositiveInfinite (VMax);
86 
87   if (InfiniteUMin && InfiniteUMax) {
88     UMin = - Infinite;
89     UMax =   Infinite;
90   }
91   else if (InfiniteUMin)
92     UMin = UMax - Infinite;
93   else if (InfiniteUMax)
94     UMax = UMin + Infinite;
95 
96   if (InfiniteVMin && InfiniteVMax) {
97     VMin = - Infinite;
98     VMax =   Infinite;
99   }
100   else if (InfiniteVMin)
101     VMin = VMax - Infinite;
102   else if (InfiniteVMax)
103     VMax = VMin + Infinite;
104 
105   for (ExpEdges.Init (TF, TopAbs_EDGE); // Edges of the face TF
106        ExpEdges.More();
107        ExpEdges.Next()) ne++;
108 
109   if (DS.FaceHasIntL(TF)) {             // OutLines built on face TF.
110 
111     TopTools_ListIteratorOfListOfShape itE;
112     for(itE.Initialize(DS.FaceIntL(TF));
113 	itE.More();
114 	itE.Next())
115       ne++;
116   }
117 
118   TopTools_Array1OfShape SH(1,ne);
119   TColStd_Array1OfBoolean IL(1,ne); // internal OutLine
120 
121   for (ExpEdges.Init (TF, TopAbs_EDGE);
122        ExpEdges.More();
123        ExpEdges.Next()) {
124     Standard_Integer IndE;
125     const TopoDS_Edge& newE = TopoDS::Edge(ExpEdges.Current());
126     const Handle(Geom2d_Curve) PC =
127       BRep_Tool::CurveOnSurface (newE, TF, U1, U2);
128     if(   Abs(PC->FirstParameter() - U1) <= Precision::PConfusion()
129        && Abs(PC->LastParameter()  - U2) <= Precision::PConfusion()) {
130       IndE = Hatcher.AddElement (PC,  newE.Orientation());
131     }
132     else {
133       Handle (Geom2d_TrimmedCurve) TPC =
134 	new Geom2d_TrimmedCurve (PC, U1, U2);
135       Geom2dAdaptor_Curve aGAC (TPC);
136       IndE = Hatcher.AddElement (aGAC, newE.Orientation());
137     }
138     SH(IndE) = newE;
139     if (DS.IsOutLFaceEdge(TF,newE)) IL(IndE) = Standard_True;
140     else                            IL(IndE) = Standard_False;
141   }
142 
143   if (DS.FaceHasIntL(TF)) { // get the internal OutLines built on face F.
144     TopTools_ListIteratorOfListOfShape itE;
145     for(itE.Initialize(DS.FaceIntL(TF));
146 	itE.More();
147 	itE.Next()) {
148       Standard_Integer IndE;
149       const TopoDS_Edge& newE = TopoDS::Edge(itE.Value());
150       const Handle(Geom2d_Curve) PC =
151 	BRep_Tool::CurveOnSurface (newE, TF, U1, U2);
152       if(   Abs(PC->FirstParameter() - U1) <= Precision::PConfusion()
153 	 && Abs(PC->LastParameter()  - U2) <= Precision::PConfusion()) {
154 	IndE = Hatcher.AddElement (PC,  TopAbs_INTERNAL);
155       }
156       else {
157 	Handle (Geom2d_TrimmedCurve) TPC =
158 	  new Geom2d_TrimmedCurve (PC, U1, U2);
159         Geom2dAdaptor_Curve aGAC (TPC);
160 	IndE = Hatcher.AddElement (aGAC, TopAbs_INTERNAL);
161       }
162       SH(IndE) = newE;
163       IL(IndE) = Standard_True;
164     }
165   }
166 
167   //-----------------------------------------------------------------------
168   // Creation des hachures.
169   //-----------------------------------------------------------------------
170 
171   BRepAdaptor_Surface Surface (TF);
172   Standard_Real Tolerance = BRep_Tool::Tolerance (TF);
173 
174   Standard_Integer IIso;
175   Standard_Real DeltaU = Abs (UMax - UMin);
176   Standard_Real DeltaV = Abs (VMax - VMin);
177   Standard_Real Confusion = Min (DeltaU, DeltaV) * HatcherConfusion3d;
178   Hatcher.Confusion3d (Confusion);
179 
180   //-----------------------------------------------------------------------
181   // Courbes Iso U.
182   //-----------------------------------------------------------------------
183 
184   Standard_Real StepU = DeltaU / (Standard_Real) nbIsos;
185   if (StepU > Confusion) {
186     Standard_Real UPrm = UMin + StepU / 2.;
187     gp_Dir2d Dir (0., 1.);
188 
189     for (IIso = 1; IIso <= nbIsos; IIso++) {
190       gp_Pnt2d Ori (UPrm, 0.);
191       Handle (Geom2d_Line) IsoLine = new Geom2d_Line (Ori, Dir);
192 
193       Geom2dAdaptor_Curve aGAC (IsoLine);
194       Standard_Integer IndH = Hatcher.AddHatching (aGAC);
195       Hatcher.Trim (IndH);
196       if (Hatcher.TrimDone (IndH) && !Hatcher.TrimFailed (IndH))
197 	Hatcher.ComputeDomains (IndH);
198       if (!Hatcher.IsDone (IndH)) {
199 #ifdef OCCT_DEBUG
200         std::cout << "HLRTopoBRep::MakeIsoLines : Face " << FI << std::endl;
201 	std::cout << "U iso of parameter: " << UPrm;
202 	switch (Hatcher.Status (IndH)) {
203 	case HatchGen_NoProblem          :
204 	  std::cout << " No Problem"          << std::endl;
205 	  break;
206 	case HatchGen_TrimFailure        :
207 	  std::cout << " Trim Failure"        << std::endl;
208 	  break;
209 	case HatchGen_TransitionFailure  :
210 	  std::cout << " Transition Failure"  << std::endl;
211 	  break;
212 	case HatchGen_IncoherentParity   :
213 	  std::cout << " Incoherent Parity"   << std::endl;
214 	  break;
215 	case HatchGen_IncompatibleStates :
216 	  std::cout << " Incompatible States" << std::endl;
217 	  break;
218 	}
219 #endif
220 	Hatcher.RemHatching (IndH);
221 	continue;
222       }
223 
224       Standard_Integer NbDom = Hatcher.NbDomains (IndH);
225       if (NbDom > 0) {
226 
227 	for (Standard_Integer IDom = 1; IDom <= NbDom; IDom++) {
228 	  const HatchGen_Domain& Dom = Hatcher.Domain (IndH, IDom);
229 	  Standard_Real U11 = Dom.HasFirstPoint()  ?
230 	    Dom.FirstPoint().Parameter()  : VMin - Infinite;
231 	  Standard_Real U21 = Dom.HasSecondPoint() ?
232 	    Dom.SecondPoint().Parameter() : VMax + Infinite;
233 	  IsoLine->D0 (U11, P);
234 	  Surface.D0 (P.X(), P.Y(), P1);
235 	  IsoLine->D0 (U21, P);
236 	  Surface.D0 (P.X(), P.Y(), P2);
237 	  if (Dom.HasFirstPoint()) { // Iso U - Premier point
238 	    const HatchGen_PointOnHatching& PntH = Dom.FirstPoint();
239 
240 	    for (Standard_Integer IPntE = 1;
241 		 IPntE <= PntH.NbPoints();
242 		 IPntE++) {
243 	      const HatchGen_PointOnElement& PntE = PntH.Point(IPntE);
244 	      V1U = HLRTopoBRep_FaceIsoLiner::MakeVertex
245 		(TopoDS::Edge(SH(PntE.Index())),
246 		 P1,PntE.Parameter(),Tolerance,DS);
247 	      if (IL(PntE.Index())) DS.AddOutV(V1U);
248 	    }
249 	  }
250 	  if (Dom.HasSecondPoint()) { // Iso U - Deuxieme point
251 	    const HatchGen_PointOnHatching& PntH = Dom.SecondPoint();
252 
253 	    for (Standard_Integer IPntE = 1;
254 		 IPntE <= PntH.NbPoints();
255 		 IPntE++) {
256 	      const HatchGen_PointOnElement& PntE = PntH.Point(IPntE);
257 	      V2U = HLRTopoBRep_FaceIsoLiner::MakeVertex
258 		(TopoDS::Edge(SH(PntE.Index())),
259 		 P2,PntE.Parameter(),Tolerance,DS);
260 	      if (IL(PntE.Index())) DS.AddOutV(V2U);
261 	    }
262 	  }
263 	  if(!V1U.IsNull() && !V2U.IsNull())
264 	    HLRTopoBRep_FaceIsoLiner::MakeIsoLine
265 	      (F,IsoLine,V1U,V2U,U11,U21,Tolerance,DS);
266 	}
267       }
268 
269       Hatcher.RemHatching (IndH);
270       UPrm += StepU;
271     }
272   }
273 
274   //-----------------------------------------------------------------------
275   // Courbes Iso V.
276   //-----------------------------------------------------------------------
277 
278   Standard_Real StepV = DeltaV / (Standard_Real) nbIsos;
279   if (StepV > Confusion) {
280     Standard_Real VPrm = VMin + StepV / 2.;
281     gp_Dir2d Dir (1., 0.);
282 
283     for (IIso = 1; IIso <= nbIsos; IIso++) {
284       gp_Pnt2d Ori (0., VPrm);
285       Handle (Geom2d_Line) IsoLine = new Geom2d_Line (Ori, Dir);
286 
287       Geom2dAdaptor_Curve aGAC (IsoLine);
288       Standard_Integer IndH = Hatcher.AddHatching (aGAC);
289       Hatcher.Trim (IndH);
290       if (Hatcher.TrimDone (IndH) && !Hatcher.TrimFailed (IndH))
291 	Hatcher.ComputeDomains (IndH);
292       if (!Hatcher.IsDone (IndH)) {
293 #ifdef OCCT_DEBUG
294 	std::cout << "HLRTopoBRep::MakeIsoLines : Face " << FI << std::endl;
295 	std::cout << "V iso of parameter: " << VPrm;
296 	switch (Hatcher.Status (IndH)) {
297 	case HatchGen_NoProblem          :
298 	  std::cout << " No Problem"          << std::endl;
299 	  break;
300 	case HatchGen_TrimFailure        :
301 	  std::cout << " Trim Failure"        << std::endl;
302 	  break;
303 	case HatchGen_TransitionFailure  :
304 	  std::cout << " Transition Failure"  << std::endl;
305 	  break;
306 	case HatchGen_IncoherentParity   :
307 	  std::cout << " Incoherent Parity"   << std::endl;
308 	  break;
309 	case HatchGen_IncompatibleStates :
310 	  std::cout << " Incompatible States" << std::endl;
311 	  break;
312 	}
313 #endif
314 	Hatcher.RemHatching (IndH);
315 	continue;
316       }
317 
318       Standard_Integer NbDom = Hatcher.NbDomains (IndH);
319       if (NbDom > 0) {
320 
321 	for (Standard_Integer IDom = 1; IDom <= NbDom; IDom++) {
322 	  const HatchGen_Domain& Dom = Hatcher.Domain (IndH, IDom);
323 	  Standard_Real U12 = Dom.HasFirstPoint()  ?
324 	    Dom.FirstPoint().Parameter()  : VMin - Infinite;
325 	  Standard_Real U22 = Dom.HasSecondPoint() ?
326 	    Dom.SecondPoint().Parameter() : VMax + Infinite;
327 	  IsoLine->D0 (U12, P);
328 	  Surface.D0 (P.X(), P.Y(), P1);
329 	  IsoLine->D0 (U22, P);
330 	  Surface.D0 (P.X(), P.Y(), P2);
331 	  if (Dom.HasFirstPoint()) { // Iso V - Premier point
332 	    const HatchGen_PointOnHatching& PntH = Dom.FirstPoint();
333 
334 	    for (Standard_Integer IPntE = 1;
335 		 IPntE <= PntH.NbPoints();
336 		 IPntE++) {
337 	      const HatchGen_PointOnElement& PntE = PntH.Point(IPntE);
338 	      V1V = HLRTopoBRep_FaceIsoLiner::MakeVertex
339 		(TopoDS::Edge(SH(PntE.Index())),
340 		 P1,PntE.Parameter(),Tolerance,DS);
341 
342      if (IL(PntE.Index())) DS.AddOutV(V1V);
343 	    }
344 	  }
345 	  if (Dom.HasSecondPoint()) { // Iso V - Deuxieme point
346 	    const HatchGen_PointOnHatching& PntH = Dom.SecondPoint();
347 
348 	    for (Standard_Integer IPntE = 1;
349 		 IPntE <= PntH.NbPoints();
350 		 IPntE++) {
351 	      const HatchGen_PointOnElement& PntE = PntH.Point(IPntE);
352 	      V2V = HLRTopoBRep_FaceIsoLiner::MakeVertex
353 		(TopoDS::Edge(SH(PntE.Index())),
354 		 P2,PntE.Parameter(),Tolerance,DS);
355 	      if (IL(PntE.Index())) DS.AddOutV(V2V);
356 	    }
357 	  }
358 	  if(!V1V.IsNull() && !V2V.IsNull())
359 	    HLRTopoBRep_FaceIsoLiner::MakeIsoLine
360 	      (F,IsoLine,V1V,V2V,U12,U22,Tolerance,DS);
361 	}
362       }
363 
364       Hatcher.RemHatching (IndH);
365       VPrm += StepV;
366     }
367   }
368 }
369 
370 //=======================================================================
371 //function : MakeVertex
372 //purpose  :
373 //=======================================================================
374 
375 TopoDS_Vertex
MakeVertex(const TopoDS_Edge & E,const gp_Pnt & P,const Standard_Real Par,const Standard_Real Tol,HLRTopoBRep_Data & DS)376 HLRTopoBRep_FaceIsoLiner::MakeVertex (const TopoDS_Edge& E,
377 				      const gp_Pnt& P,
378 				      const Standard_Real Par,
379 				      const Standard_Real Tol,
380 				      HLRTopoBRep_Data& DS)
381 {
382   TopoDS_Vertex V, VF, VL;
383   BRep_Builder B;
384   TopExp::Vertices (E, VF, VL);
385   if (P.IsEqual(BRep_Tool::Pnt(VF),BRep_Tool::Tolerance(VF)))
386     return VF;
387   if (P.IsEqual(BRep_Tool::Pnt(VL),BRep_Tool::Tolerance(VL)))
388     return VL;
389 
390   for (DS.InitVertex(E); DS.MoreVertex(); DS.NextVertex()) {
391     TopoDS_Vertex curV = DS.Vertex();
392     Standard_Real curP = DS.Parameter();
393     if (P.IsEqual(BRep_Tool::Pnt(curV),BRep_Tool::Tolerance(curV))) {
394       V = curV;
395       break;
396     }
397     else if (Par < curP) {
398       B.MakeVertex(V,P,Tol);
399       V.Orientation(TopAbs_INTERNAL);
400       DS.InsertBefore(V,Par);
401       break;
402     }
403   }
404 
405   if (!DS.MoreVertex()) {
406     B.MakeVertex(V,P,Tol);
407     V.Orientation(TopAbs_INTERNAL);
408     DS.Append(V,Par);
409   }
410 
411   return V;
412 }
413 
414 //=======================================================================
415 //function : MakeIsoLine
416 //purpose  :
417 //=======================================================================
418 
MakeIsoLine(const TopoDS_Face & F,const Handle (Geom2d_Line)& Iso,TopoDS_Vertex & V1,TopoDS_Vertex & V2,const Standard_Real U1,const Standard_Real U2,const Standard_Real Tol,HLRTopoBRep_Data & DS)419 void HLRTopoBRep_FaceIsoLiner::MakeIsoLine (const TopoDS_Face& F,
420 					    const Handle(Geom2d_Line)& Iso,
421 					    TopoDS_Vertex& V1,
422 					    TopoDS_Vertex& V2,
423 					    const Standard_Real U1,
424 					    const Standard_Real U2,
425 					    const Standard_Real Tol,
426 					    HLRTopoBRep_Data& DS)
427 {
428   BRep_Builder B;
429   TopoDS_Edge E;
430   E.Orientation (TopAbs_INTERNAL);
431   V1.Orientation (TopAbs_FORWARD);
432   V2.Orientation (TopAbs_REVERSED);
433   B.MakeEdge (E);
434   B.UpdateEdge (E, Iso, F, Tol);
435   B.Add (E, V1);
436   B.UpdateVertex (V1, U1, E, Tol);
437   B.Add (E, V2);
438   B.UpdateVertex (V2, U2, E, Tol);
439   DS.AddIsoL(F).Append(E);
440 }
441 
442