0022048: Visualization, AIS_InteractiveContext - single object selection should alway...
[occt.git] / src / TopOpeBRepTool / TopOpeBRepTool_2d.cxx
1 // Created on: 1998-03-23
2 // Created by: Jean Yves LEBEY
3 // Copyright (c) 1998-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 <gp_Vec2d.hxx>
18 #include <TopoDS.hxx>
19 #include <TopExp.hxx>
20 #include <TopOpeBRepTool_2d.hxx>
21 #include <BRep_Tool.hxx>
22 #include <Geom_Curve.hxx>
23 #include <ProjLib_ProjectedCurve.hxx>
24 #include <Geom_Surface.hxx>
25 #include <BRepAdaptor_Surface.hxx>
26 #include <BRepAdaptor_Curve.hxx>
27 #include <BRepAdaptor_HSurface.hxx>
28 #include <BRepAdaptor_HCurve.hxx>
29 #include <GeomAdaptor_Curve.hxx>
30 #include <GeomAdaptor_HCurve.hxx>
31 #include <Geom_TrimmedCurve.hxx>
32 #include <TopOpeBRepTool_CurveTool.hxx>
33 #include <TopOpeBRepTool_DataMapOfShapeListOfC2DF.hxx>
34 #include <TopOpeBRepTool_C2DF.hxx>
35 #include <TopOpeBRepTool_ListOfC2DF.hxx>
36 #include <TopOpeBRepTool_ListIteratorOfListOfC2DF.hxx>
37 #include <TopOpeBRepTool_tol.hxx>
38 #include <TopOpeBRepTool_EXPORT.hxx>
39 #include <TopOpeBRepTool_TOOL.hxx>
40
41 #ifdef DRAW
42 #include <TopOpeBRepTool_DRAW.hxx>
43 #include <Geom2d_Curve.hxx>
44 #endif
45
46 #ifdef OCCT_DEBUG
47 void debc2dnull(void) {}
48 Standard_EXPORT Standard_Boolean TopOpeBRepTool_GettraceC2D();
49 #endif
50
51 // structure e -> C2D/F
52 static TopOpeBRepTool_DataMapOfShapeListOfC2DF *GLOBAL_pmosloc2df = NULL;
53 static Standard_Integer GLOBAL_C2D_i = 0; // DEB
54
55 // structure ancetre
56 static TopTools_IndexedDataMapOfShapeListOfShape *GLOBAL_pidmoslosc2df = NULL; 
57 static TopoDS_Face *GLOBAL_pFc2df = NULL;
58 static TopoDS_Shape *GLOBAL_pS1c2df = NULL;
59 static TopoDS_Shape *GLOBAL_pS2c2df = NULL;
60
61 Standard_EXPORT Handle(Geom2d_Curve) MakePCurve(const ProjLib_ProjectedCurve& PC);
62
63 // ------------------------------------------------------------------------------------
64 static const TopoDS_Face& FC2D_FancestorE(const TopoDS_Edge& E)
65 {
66   if (GLOBAL_pmosloc2df == NULL) GLOBAL_pmosloc2df = new TopOpeBRepTool_DataMapOfShapeListOfC2DF();
67   Standard_Integer ancemp = (*GLOBAL_pidmoslosc2df).Extent();
68   if (ancemp == 0) {
69     TopExp::MapShapesAndAncestors(*GLOBAL_pS1c2df,TopAbs_EDGE,TopAbs_FACE,(*GLOBAL_pidmoslosc2df));  
70     TopExp::MapShapesAndAncestors(*GLOBAL_pS2c2df,TopAbs_EDGE,TopAbs_FACE,(*GLOBAL_pidmoslosc2df));  
71   }
72   Standard_Boolean Eb = (*GLOBAL_pidmoslosc2df).Contains(E);
73   if ( !Eb ) return *GLOBAL_pFc2df;
74   const TopTools_ListOfShape& lf = (*GLOBAL_pidmoslosc2df).FindFromKey(E);
75   if (lf.IsEmpty()) return *GLOBAL_pFc2df;
76   const TopoDS_Face& F = TopoDS::Face(lf.First());
77   return F;
78 }
79
80 // ------------------------------------------------------------------------------------
81 Standard_EXPORT int FC2D_Prepare(const TopoDS_Shape& S1,const TopoDS_Shape& S2)
82 {
83   if (GLOBAL_pmosloc2df == NULL) GLOBAL_pmosloc2df = new TopOpeBRepTool_DataMapOfShapeListOfC2DF();
84   GLOBAL_pmosloc2df->Clear();
85   GLOBAL_C2D_i = 0;
86
87   if (GLOBAL_pidmoslosc2df == NULL) GLOBAL_pidmoslosc2df = new TopTools_IndexedDataMapOfShapeListOfShape();
88   GLOBAL_pidmoslosc2df->Clear();
89
90   if (GLOBAL_pFc2df == NULL) GLOBAL_pFc2df = new TopoDS_Face();
91   GLOBAL_pFc2df->Nullify();
92
93   if (GLOBAL_pS1c2df == NULL) GLOBAL_pS1c2df = new TopoDS_Shape();
94   *GLOBAL_pS1c2df = S1;
95
96   if (GLOBAL_pS2c2df == NULL) GLOBAL_pS2c2df = new TopoDS_Shape();
97   *GLOBAL_pS2c2df = S2;
98
99   return 0;
100 }
101
102 // ------------------------------------------------------------------------------------
103 Standard_EXPORT Standard_Boolean FC2D_HasC3D(const TopoDS_Edge& E)
104 {
105   TopLoc_Location loc; Standard_Real f3d,l3d; Handle(Geom_Curve) C3D = BRep_Tool::Curve(E,loc,f3d,l3d);
106   Standard_Boolean b = (!C3D.IsNull());
107   return b;
108 }
109
110 // ------------------------------------------------------------------------------------
111 Standard_EXPORT Standard_Boolean FC2D_HasCurveOnSurface(const TopoDS_Edge& E,const TopoDS_Face& F)
112 {
113   Handle(Geom2d_Curve) C2D;
114   Standard_Boolean hasold = FC2D_HasOldCurveOnSurface(E,F,C2D);
115   Standard_Boolean hasnew = FC2D_HasNewCurveOnSurface(E,F,C2D);
116   Standard_Boolean b = hasold || hasnew;
117   return b;
118 }
119
120 // ------------------------------------------------------------------------------------
121 Standard_EXPORT Standard_Boolean FC2D_HasOldCurveOnSurface(const TopoDS_Edge& E,const TopoDS_Face& F,Handle(Geom2d_Curve)& C2D,Standard_Real& f2d,Standard_Real& l2d,Standard_Real& tol)
122 {
123   Standard_Boolean hasold = Standard_False;
124   tol = BRep_Tool::Tolerance(E);
125   C2D = BRep_Tool::CurveOnSurface(E,F,f2d,l2d);
126   hasold = (!C2D.IsNull());
127   return hasold;
128 }
129 Standard_EXPORT Standard_Boolean FC2D_HasOldCurveOnSurface(const TopoDS_Edge& E,const TopoDS_Face& F,Handle(Geom2d_Curve)& C2D)
130 { Standard_Real f2d,l2d,tol; Standard_Boolean hasold = FC2D_HasOldCurveOnSurface(E,F,C2D,f2d,l2d,tol); return hasold;
131 }
132
133 // ------------------------------------------------------------------------------------
134 static TopOpeBRepTool_C2DF* FC2D_PNewCurveOnSurface(const TopoDS_Edge& E,const TopoDS_Face& F)
135 {
136   TopOpeBRepTool_C2DF* pc2df = NULL;
137   if (GLOBAL_pmosloc2df == NULL) return NULL;
138   Standard_Boolean Eisb = GLOBAL_pmosloc2df->IsBound(E);
139   if (!Eisb) return NULL;
140   TopOpeBRepTool_ListIteratorOfListOfC2DF it(GLOBAL_pmosloc2df->Find(E));
141   for(;it.More();it.Next()) {
142     const TopOpeBRepTool_C2DF& c2df = it.Value();
143     Standard_Boolean isf = c2df.IsFace(F);
144     if (isf) {
145       pc2df = (TopOpeBRepTool_C2DF*)&c2df;
146       break;
147     }
148   }
149   return pc2df;
150 }
151 Standard_EXPORT Standard_Boolean FC2D_HasNewCurveOnSurface(const TopoDS_Edge& E,const TopoDS_Face& F,Handle(Geom2d_Curve)& C2D,Standard_Real& f2d,Standard_Real& l2d,Standard_Real& tol)
152 {
153   const TopOpeBRepTool_C2DF* pc2df = FC2D_PNewCurveOnSurface(E,F);
154   Standard_Boolean hasnew = (pc2df != NULL);
155   if (hasnew) C2D = pc2df->PC(f2d,l2d,tol);
156   return hasnew;
157 }
158 Standard_EXPORT Standard_Boolean FC2D_HasNewCurveOnSurface(const TopoDS_Edge& E,const TopoDS_Face& F,Handle(Geom2d_Curve)& C2D)
159 { Standard_Real f2d,l2d,tol; Standard_Boolean b = FC2D_HasNewCurveOnSurface(E,F,C2D,f2d,l2d,tol); return b;
160 }
161
162 // ------------------------------------------------------------------------------------
163 Standard_Integer FC2D_AddNewCurveOnSurface(Handle(Geom2d_Curve) C2D,const TopoDS_Edge& E,const TopoDS_Face& F,const Standard_Real& f2d,const Standard_Real& l2d,const Standard_Real& tol)
164 {
165   if (C2D.IsNull()) return 1;
166   TopOpeBRepTool_C2DF c2df(C2D,f2d,l2d,tol,F);
167   if (GLOBAL_pmosloc2df == NULL) return 1;
168   TopOpeBRepTool_ListOfC2DF thelist;
169   GLOBAL_pmosloc2df->Bind(E, thelist);
170   TopOpeBRepTool_ListOfC2DF& lc2df = GLOBAL_pmosloc2df->ChangeFind(E);
171   lc2df.Append(c2df);
172   return 0;
173 }
174
175 // ------------------------------------------------------------------------------------
176 static Handle(Geom2d_Curve) FC2D_make2d(const TopoDS_Edge& E,const TopoDS_Face& F,Standard_Real& f2d,Standard_Real& l2d,Standard_Real& tol,const Standard_Boolean trim3d = Standard_False);
177 static Handle(Geom2d_Curve) FC2D_make2d(const TopoDS_Edge& E,const TopoDS_Face& F,Standard_Real& f2d,Standard_Real& l2d,Standard_Real& tol,const Standard_Boolean trim3d)
178 {
179   Handle(Geom2d_Curve) C2D = BRep_Tool::CurveOnSurface(E,F,f2d,l2d);
180   if (!C2D.IsNull()) return C2D;
181
182   // pas de 2D
183   Standard_Real f3d,l3d;TopLoc_Location eloc;
184   Handle(Geom_Curve) C1 = BRep_Tool::Curve(E,eloc,f3d,l3d);
185   Standard_Boolean hasC3D = (!C1.IsNull());
186
187   if ( hasC3D ) {
188     Standard_Boolean elocid = eloc.IsIdentity();
189     Handle(Geom_Curve) C2;
190     if (elocid ) C2 = C1;
191     else C2 = Handle(Geom_Curve)::DownCast(C1->Transformed(eloc.Transformation()));
192     Standard_Real f=0.,l=0.;
193     if (trim3d) {f=f3d; l=l3d;}
194     C2D = TopOpeBRepTool_CurveTool::MakePCurveOnFace(F,C2,tol,f,l);
195     f2d = f3d; l2d = l3d;
196     return C2D;
197   }
198   else {
199     // E sans courbe 2d sur F, E sans courbe 3d
200     // une face accedant a E : FE
201     const TopoDS_Face& FE = FC2D_FancestorE(E);
202     if (FE.IsNull()) return C2D;
203     Standard_Boolean compminmaxUV = Standard_False;
204     BRepAdaptor_Surface BAS(F,compminmaxUV);
205     Handle(BRepAdaptor_HSurface) BAHS = new BRepAdaptor_HSurface(BAS);
206     BRepAdaptor_Curve AC(E,FE);
207     Handle(BRepAdaptor_HCurve) AHC = new BRepAdaptor_HCurve(AC);
208     Standard_Real tolin; FTOL_FaceTolerances3d(F,FE,tolin);
209     ProjLib_ProjectedCurve projcurv(BAHS,AHC,tolin);    
210     C2D = MakePCurve(projcurv);
211     Standard_Real f,l; BRep_Tool::Range(E,f,l);
212     f2d = f; l2d = l;
213   }
214   
215 #ifdef OCCT_DEBUG
216   if (TopOpeBRepTool_GettraceC2D() && C2D.IsNull()) {
217     cout<<"#FC2D_make2d1 --> PCurve IsNull"<<endl;
218   }
219 #endif
220
221   return C2D;
222 } // make2d1
223
224 // ------------------------------------------------------------------------------------
225 //modified by NIZHNY-MZV  Mon Oct  4 10:37:36 1999
226 Standard_EXPORT Handle(Geom2d_Curve) FC2D_MakeCurveOnSurface(const TopoDS_Edge& E,const TopoDS_Face& F,Standard_Real& f,Standard_Real& l,Standard_Real& tol,const Standard_Boolean trim3d)
227 {
228 #ifdef DRAW
229   if (TopOpeBRepTool_GettraceC2D()) {
230     cout<<"\n#FC2D_MakeCurveOnSurface : "<<endl;
231     TCollection_AsciiString fnam("c2df");GLOBAL_C2D_i++;fnam=fnam+GLOBAL_C2D_i;FDRAW_DINS("",F,fnam,"");
232     TCollection_AsciiString enam("c2de");GLOBAL_C2D_i++;enam=enam+GLOBAL_C2D_i;FDRAW_DINE(" ",E,enam,"\n");
233     cout.flush(); debc2dnull();
234   }
235 #endif
236   
237   Handle(Geom2d_Curve) C2D = FC2D_make2d(E,F,f,l,tol,trim3d);
238   FC2D_AddNewCurveOnSurface(C2D,E,F,f,l,tol);
239   return C2D;
240 }
241
242 // ------------------------------------------------------------------------------------
243 Standard_EXPORT Handle(Geom2d_Curve) FC2D_CurveOnSurface(const TopoDS_Edge& E,const TopoDS_Face& F,Standard_Real& f,Standard_Real& l,Standard_Real& tol,const Standard_Boolean trim3d)
244 {
245   Handle(Geom2d_Curve) C2D;
246   Standard_Boolean hasold = FC2D_HasOldCurveOnSurface(E,F,C2D,f,l,tol);
247   if (hasold) {
248     return C2D;
249   }
250   Standard_Boolean hasnew = FC2D_HasNewCurveOnSurface(E,F,C2D,f,l,tol);
251   if (hasnew) {
252     return C2D;
253   }
254   C2D = FC2D_MakeCurveOnSurface(E,F,f,l,tol,trim3d);
255   return C2D;
256 }
257
258 // ------------------------------------------------------------------------------------
259 Standard_EXPORT Handle(Geom2d_Curve) FC2D_EditableCurveOnSurface(const TopoDS_Edge& E,const TopoDS_Face& F,Standard_Real& f,Standard_Real& l,Standard_Real& tol,const Standard_Boolean trim3d)
260 {
261   Standard_Boolean hasold = Standard_False;
262   {
263     Handle(Geom2d_Curve) C2D;
264     hasold = FC2D_HasOldCurveOnSurface(E,F,C2D,f,l,tol);
265     if (hasold) {
266       Handle(Geom2d_Curve) copC2D = Handle(Geom2d_Curve)::DownCast(C2D->Copy());
267       return copC2D;
268     }
269   }
270   Standard_Boolean hasnew = Standard_False;
271   {
272     Handle(Geom2d_Curve) newC2D;
273     hasnew = FC2D_HasNewCurveOnSurface(E,F,newC2D,f,l,tol);
274     if (hasnew) {
275       return newC2D;
276     }  
277   }
278   Handle(Geom2d_Curve) makC2D = FC2D_MakeCurveOnSurface(E,F,f,l,tol,trim3d);
279   return makC2D;
280 }
281
282 // ------------------------------------------------------------------------------------
283 static void FC2D_translate(Handle(Geom2d_Curve) C2D,
284 //                           const TopoDS_Edge& E,
285                            const TopoDS_Edge& ,
286                            const TopoDS_Face& F,
287                            const TopoDS_Edge& EF)
288 {
289   TopLoc_Location sloc; const Handle(Geom_Surface)& S1 = BRep_Tool::Surface(F,sloc);
290   Standard_Boolean isperio = S1->IsUPeriodic() || S1->IsVPeriodic();
291   gp_Dir2d d2d; gp_Pnt2d O2d; Standard_Boolean isuiso,isviso; 
292   Standard_Boolean uviso = TopOpeBRepTool_TOOL::UVISO(C2D,isuiso,isviso,d2d,O2d);
293   Standard_Boolean EFnull = EF.IsNull();
294   
295   if (isperio && uviso && !EFnull) {
296     // C2D prend comme origine dans F l'origine de la pcurve de EF dans F
297     TopoDS_Face FFOR = F;
298     FFOR.Orientation(TopAbs_FORWARD);
299     gp_Pnt2d p1,p2; BRep_Tool::UVPoints(EF,FFOR,p1,p2);
300     Standard_Real pEF = isuiso ? p1.X() : p1.Y();
301     Standard_Real pC2D = isuiso ? O2d.X() : O2d.Y();
302     Standard_Real factor = pEF - pC2D;
303     Standard_Boolean b = (Abs(factor) > 1.e-6);
304     if ( b ) {
305       gp_Vec2d transl(1.,0.); if (isviso) transl = gp_Vec2d(0.,1.);
306       transl.Multiply(factor);
307       C2D->Translate(transl);
308     }
309   }
310 }
311
312 // ------------------------------------------------------------------------------------
313 static Handle(Geom2d_Curve) FC2D_make2d(const TopoDS_Edge& E,const TopoDS_Face& F,const TopoDS_Edge& EF,Standard_Real& f2d,Standard_Real& l2d,Standard_Real& tol,const Standard_Boolean trim3d = Standard_False);
314 static Handle(Geom2d_Curve) FC2D_make2d(const TopoDS_Edge& E,const TopoDS_Face& F,const TopoDS_Edge& EF,Standard_Real& f2d,Standard_Real& l2d,Standard_Real& tol,const Standard_Boolean trim3d)
315 {
316   Handle(Geom2d_Curve) C2D = BRep_Tool::CurveOnSurface(E,F,f2d,l2d);
317   if (!C2D.IsNull()) return C2D;
318
319   // pas de 2D
320   Standard_Real f3d,l3d;TopLoc_Location eloc;
321   Handle(Geom_Curve) C1 = BRep_Tool::Curve(E,eloc,f3d,l3d);
322   Standard_Boolean hasC3D = (!C1.IsNull());
323
324   if ( hasC3D ) {
325     Standard_Boolean elocid = eloc.IsIdentity();
326     Handle(Geom_Curve) C2;
327     if (elocid ) C2 = C1;
328     else C2 = Handle(Geom_Curve)::DownCast(C1->Transformed(eloc.Transformation()));
329     Standard_Real f=0.,l=0.;
330     if (trim3d) {f=f3d; l=l3d;}
331     C2D = TopOpeBRepTool_CurveTool::MakePCurveOnFace(F,C2,tol,f,l);
332     f2d = f3d; l2d = l3d;
333     FC2D_translate(C2D,E,F,EF);
334     return C2D;
335   }
336   else {
337     // E sans courbe 2d sur F, E sans courbe 3d
338     // une face accedant a E : FE
339     const TopoDS_Face& FE = FC2D_FancestorE(E);
340     if (FE.IsNull()) return C2D;
341     Standard_Boolean compminmaxUV = Standard_False;
342     BRepAdaptor_Surface BAS(F,compminmaxUV);
343     Handle(BRepAdaptor_HSurface) BAHS = new BRepAdaptor_HSurface(BAS);
344     BRepAdaptor_Curve AC(E,FE);
345     Handle(BRepAdaptor_HCurve) AHC = new BRepAdaptor_HCurve(AC);
346     Standard_Real tolin; FTOL_FaceTolerances3d(F,FE,tolin);
347     ProjLib_ProjectedCurve projcurv(BAHS,AHC,tolin);
348     C2D = MakePCurve(projcurv);
349     Standard_Real f,l; BRep_Tool::Range(E,f,l);
350     f2d = f; l2d = l;
351     FC2D_translate(C2D,E,F,EF);
352   }
353
354 #ifdef OCCT_DEBUG
355   if (TopOpeBRepTool_GettraceC2D() && C2D.IsNull()) {
356     cout<<"#FC2D_make2d2 --> PCurve IsNull"<<endl;
357   }
358 #endif
359
360   return C2D;
361 } // make2d2
362
363 // ------------------------------------------------------------------------------------
364 Standard_EXPORT Handle(Geom2d_Curve) FC2D_CurveOnSurface(const TopoDS_Edge& E,const TopoDS_Face& F,const TopoDS_Edge& EF,Standard_Real& f2d,Standard_Real& l2d,Standard_Real& tol,const Standard_Boolean trim3d)
365 {
366   Handle(Geom2d_Curve) C2D;
367
368   Standard_Boolean hasold = FC2D_HasOldCurveOnSurface(E,F,C2D,f2d,l2d,tol);
369   if (hasold) return C2D;
370   
371   TopOpeBRepTool_C2DF* pc2df = FC2D_PNewCurveOnSurface(E,F);
372   if (pc2df != NULL) {
373     C2D = pc2df->PC(f2d,l2d,tol);
374     FC2D_translate(C2D,E,F,EF);
375     pc2df->SetPC(C2D,f2d,l2d,tol);
376     return C2D;
377   }
378   
379 #ifdef DRAW
380   if (TopOpeBRepTool_GettraceC2D()) {
381     cout<<"\n#FC2D_CurveOnSurface : "<<endl;
382     TCollection_AsciiString fnam("c2df");GLOBAL_C2D_i++;fnam=fnam+GLOBAL_C2D_i;FDRAW_DINS("",F,fnam,"");
383     TCollection_AsciiString enam("c2de");GLOBAL_C2D_i++;enam=enam+GLOBAL_C2D_i;FDRAW_DINE(" ",E,enam,"\n");
384     cout.flush();debc2dnull();
385   }
386 #endif
387   
388   C2D = FC2D_make2d(E,F,EF,f2d,l2d,tol,trim3d);
389   FC2D_AddNewCurveOnSurface(C2D,E,F,f2d,l2d,tol);
390   return C2D;
391 }