Test for 0022778: Bug in BRepMesh
[occt.git] / src / Interface / Interface_CopyTool.cxx
1 // Copyright (c) 1999-2012 OPEN CASCADE SAS
2 //
3 // The content of this file is subject to the Open CASCADE Technology Public
4 // License Version 6.5 (the "License"). You may not use the content of this file
5 // except in compliance with the License. Please obtain a copy of the License
6 // at http://www.opencascade.org and read it completely before using this file.
7 //
8 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
9 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
10 //
11 // The Original Code and all software distributed under the License is
12 // distributed on an "AS IS" basis, without warranty of any kind, and the
13 // Initial Developer hereby disclaims all such warranties, including without
14 // limitation, any warranties of merchantability, fitness for a particular
15 // purpose or non-infringement. Please see the License for the specific terms
16 // and conditions governing the rights and limitations under the License.
17
18 #include <Interface_CopyTool.ixx>
19 #include <Interface_GeneralModule.hxx>
20 #include <Interface_ReportEntity.hxx>
21 #include <Interface_InterfaceError.hxx>
22 #include <TCollection_HAsciiString.hxx>
23
24
25 // Se souvenir qu une version plus riche de CopyTool existe : c est
26 // TransferDispatch (package Transfer). Cette classe offre beaucoup plus de
27 // possibilite (parametrage des actions, gestion du Mapping ...)
28 // Mais le principe (transfert en 2 passes) reste le meme, a savoir :
29 // Passe 1 normale : les entites a transferer sont designees, elles entrainent
30 // leurs sous-references vraies
31 // Passe 2 : une fois tous les transferts faits, les relations "Imply" sont
32 // mises, pour les entites designees ET QUI ONT ETE AUSSI TRANSFEREES, la
33 // relation est reconduite (pas de nouveau Share)
34
35
36 //  #####################################################################
37 //  ....                        CONSTRUCTEURS                        ....
38
39 Interface_CopyTool::Interface_CopyTool
40   (const Handle(Interface_InterfaceModel)& amodel,
41    const Interface_GeneralLib& lib)
42     : thelib (lib) , thelst (amodel->NbEntities())
43 {
44   thelst.Init(Standard_False);
45   themod = amodel;
46   themap = new Interface_CopyMap (amodel);
47   therep = new Interface_CopyMap (amodel);
48   thelev = 0;  theimp = Standard_False;
49 }
50
51     Interface_CopyTool::Interface_CopyTool
52   (const Handle(Interface_InterfaceModel)& amodel,
53    const Handle(Interface_Protocol)& protocol)
54     : thelib (protocol) , thelst (amodel->NbEntities())
55 {
56   thelst.Init(Standard_False);
57   themod = amodel;
58   themap = new Interface_CopyMap (amodel);
59   therep = new Interface_CopyMap (amodel);
60   thelev = 0;  theimp = Standard_False;
61 }
62
63
64     Interface_CopyTool::Interface_CopyTool
65   (const Handle(Interface_InterfaceModel)& amodel)
66     : thelib (Interface_Protocol::Active()) , thelst (amodel->NbEntities())
67 {
68   if (Interface_Protocol::Active().IsNull()) Interface_InterfaceError::Raise
69     ("Interface CopyTool : Create with Active Protocol undefined");
70
71   thelst.Init(Standard_False);
72   themod = amodel;
73   themap = new Interface_CopyMap (amodel);
74   therep = new Interface_CopyMap (amodel);
75   thelev = 0;  theimp = Standard_False;
76 }
77
78     Handle(Interface_InterfaceModel)  Interface_CopyTool::Model () const
79       {  return themod;  }
80
81     void Interface_CopyTool::SetControl
82   (const Handle(Interface_CopyControl)& othermap)
83       {  themap = othermap;  }
84
85     Handle(Interface_CopyControl)  Interface_CopyTool::Control () const
86       {  return themap;  }
87
88
89 //  #####################################################################
90 //  ....                    Actions Individuelles                    ....
91
92     void Interface_CopyTool::Clear ()
93 {
94   themap->Clear();
95   therep->Clear();
96   thelev = 0;  theimp = Standard_False;
97   therts.Clear();
98   ClearLastFlags();
99 }
100
101     Standard_Boolean Interface_CopyTool::NewVoid
102   (const Handle(Standard_Transient)& entfrom,
103    Handle(Standard_Transient)& entto)
104 {
105   if (entfrom == theent) {
106     if (themdu.IsNull()) return Standard_False;
107     return themdu->NewVoid(theCN,entto);
108   }
109   theent = entfrom;
110   Standard_Boolean res = thelib.Select (entfrom,themdu,theCN);
111   if (res)   res   = themdu->NewVoid (theCN,entto);
112   if (!res)  res   = themdu->NewCopiedCase (theCN,entfrom,entto,*this);
113 //  if (!res) entto = entfrom->ShallowCopy();   sorry, nothing more possible
114   return res;
115 }
116
117
118     Standard_Boolean Interface_CopyTool::Copy
119   (const Handle(Standard_Transient)& entfrom,
120    Handle(Standard_Transient)& entto,
121    const Standard_Boolean mapped, const Standard_Boolean errstat)
122 {
123   Standard_Boolean res = Standard_True;
124   if (entfrom == theent) {
125     if (themdu.IsNull()) res = Standard_False;
126   } else {
127     theent = entfrom;
128     res = thelib.Select(entfrom,themdu,theCN);
129   }
130   if (!res) {
131 //  Built-in :
132     if (entfrom.IsNull()) return res;
133     if (entfrom->DynamicType() == STANDARD_TYPE(TCollection_HAsciiString)) {
134       entto = new TCollection_HAsciiString
135         ( Handle(TCollection_HAsciiString)::DownCast(entfrom)->ToCString() );
136       res = Standard_True;
137     }
138     return res;
139   }
140 //  On cree l Entite vide (NewVoid), la Copie reste a faire
141   res = NewVoid(entfrom,entto);
142   if (mapped) themap->Bind (entfrom,entto);    // Mapper avant de continuer ...
143
144 //  A present, on effectue la Copie (selon cas; si ShallowCopy ne suffit pas :
145 //  c est <themdu> qui decide)
146
147 //    Une Entite en Erreur n est pas copiee (pas de sens et c est risque ...)
148 //    Cependant, elle est "Copiee a Vide (NewVoid)" donc referencable
149   if (!errstat)    themdu->CopyCase(theCN,entfrom,entto,*this);
150   return res;
151 }
152
153     void  Interface_CopyTool::Implied
154   (const Handle(Standard_Transient)& entfrom,
155    const Handle(Standard_Transient)& entto)
156 {
157   Handle(Interface_GeneralModule) module;
158   Standard_Integer CN;
159   if (thelib.Select(entfrom,module,CN))
160     module->RenewImpliedCase(CN,entfrom,entto,*this);
161 }
162
163
164 //  ....                Alimentation de la Map                ....
165
166     Handle(Standard_Transient) Interface_CopyTool::Transferred
167   (const Handle(Standard_Transient)& ent)
168 {
169   Handle(Standard_Transient) res;
170   if (ent.IsNull()) return res;    // Copie d un Null : tres simple ...
171   Standard_Integer nument = themod->Number(ent);
172
173 //  <nument> == 0 -> Peut etre une sous-partie non partagee ...
174 //  On accepte mais on se protege contre un bouclage
175   if (nument == 0 && thelev > 100) Interface_InterfaceError::Raise
176     ("CopyTool : Transferred, Entity is not contained in Starting Model");
177   if (!themap->Search(ent,res)) {       // deja transfere ? sinon, le faire
178
179 //  On opere la Copie (enfin, on tente)
180 //  En cas d echec, rien n est enregistre
181     if (!Copy(ent,res, (nument != 0), themod->IsRedefinedContent(nument) ))
182       return res;
183
184     thelev ++;
185     if (nument != 0) thelst.SetTrue (nument);
186     Handle(Interface_ReportEntity) rep;
187     if (nument != 0) rep = themod->ReportEntity (nument);
188     if (!rep.IsNull()) {
189 //  ATTENTION ATTENTION, si ReportEntity : Copier aussi Content et refaire une
190 //  ReportEntity avec les termes initiaux
191       if (rep->IsUnknown()) therep->Bind
192         (ent, new Interface_ReportEntity(res));
193       else {
194         Handle(Standard_Transient) contfrom, contto;
195         contfrom = rep->Content();
196         Handle(Interface_ReportEntity) repto =
197           new Interface_ReportEntity (rep->Check(),res);
198         if (!contfrom.IsNull()) {
199           if (contfrom == ent) contto = res;
200           else  Copy (contfrom,contto, themod->Contains(contfrom), Standard_False);
201           repto->SetContent (contto);
202         }
203         therep->Bind (ent,repto);
204       }
205     }
206 //    Gerer le niveau d imbrication (0 = racine du transfert)
207     thelev --;
208   }
209   if (thelev == 0 && nument > 0) therts.Append(nument);
210   return res;
211 }
212
213     void Interface_CopyTool::Bind
214   (const Handle(Standard_Transient)& ent,
215    const Handle(Standard_Transient)& res)
216 {
217   Standard_Integer num = themod->Number(ent);
218   themap->Bind (ent,res);
219   thelst.SetTrue (num);
220 }
221
222     Standard_Boolean Interface_CopyTool::Search
223   (const Handle(Standard_Transient)& ent,
224    Handle(Standard_Transient)& res) const
225       {  return themap->Search (ent,res);  }
226
227 //  ##    ##    ##    ##    ##    ##    ##    ##    ##    ##    ##    ##    ##
228 //                              LastFlag
229
230     void Interface_CopyTool::ClearLastFlags ()
231       {  thelst.Init(Standard_False);  }
232
233     Standard_Integer  Interface_CopyTool::LastCopiedAfter
234   (const Standard_Integer numfrom,
235    Handle(Standard_Transient)& ent, Handle(Standard_Transient)& res) const
236 {
237   Standard_Integer nb = thelst.Length();
238   for (Standard_Integer num = numfrom + 1; num <= nb; num ++) {
239     if (thelst.Value(num)) {
240       ent = themod->Value(num);
241       if (themap->Search(ent,res)) return num;
242     }
243   }
244   return 0;
245 }
246
247
248 //  #########################################################################
249 //  ....                        Actions Generales                        ....
250
251     void Interface_CopyTool::TransferEntity
252   (const Handle(Standard_Transient)& ent)
253       {  Handle(Standard_Transient) res = Transferred(ent);  }
254
255     void Interface_CopyTool::RenewImpliedRefs ()
256 {
257   if (theimp) return;    // deja fait
258   theimp = Standard_True;
259
260 //  Transfert Passe 2 : recuperation des relations non "Share" (mais "Imply")
261 //  c-a-d portant sur des entites qui ont pu ou non etre transferees
262 //  (Et que la 1re passe n a pas copie mais laisse en Null)
263 //  N.B. : on devrait interdire de commander des nouveaux transferts ...
264
265   Standard_Integer nb = themod->NbEntities();
266   for (Standard_Integer i = 1; i <= nb; i ++) {
267     Handle(Standard_Transient) ent = themod->Value(i);
268     Handle(Standard_Transient) res;
269     if (!themap->Search(ent,res)) continue;        // entite pas transferee
270 //    Reconduction des references "Imply".  Attention, ne pas copier si non chargee
271     Handle(Interface_ReportEntity) rep;
272     if (!therep->Search(ent,rep))   Implied (ent,res);
273     else if (!rep->HasNewContent()) Implied (ent,res);
274   }
275 }
276
277
278     void Interface_CopyTool::FillModel
279   (const Handle(Interface_InterfaceModel)& bmodel)
280 {
281 //  Travaux preparatoires concernant les modeles
282 //  On commence : cela implique le Header
283   bmodel->Clear();
284   bmodel->GetFromAnother(themod);
285
286 //  Transfert Passe 1 : On prend les Entites prealablement copiees
287   Interface_EntityIterator list = CompleteResult(Standard_True);
288   bmodel->GetFromTransfer(list);
289
290 //  Transfert Passe 2 : recuperation des relations non "Share" (mais "Imply")
291   RenewImpliedRefs();
292 }
293
294
295     Interface_EntityIterator Interface_CopyTool::CompleteResult
296   (const Standard_Boolean withreports) const
297 {
298   Interface_EntityIterator iter;
299   Standard_Integer nb = themod->NbEntities();
300   for (Standard_Integer i = 1; i <= nb; i ++) {
301     Handle(Standard_Transient) ent = themod->Value(i);
302     Handle(Standard_Transient) res;
303     if (!themap->Search(ent,res)) continue;
304     if (withreports) {
305       Handle(Interface_ReportEntity) rep;
306       if (therep->Search(ent,rep)) res = rep;
307     }
308     iter.GetOneItem(res);
309   }
310   return iter;
311 }
312
313     Interface_EntityIterator Interface_CopyTool::RootResult
314   (const Standard_Boolean withreports) const
315 {
316   Interface_EntityIterator iter;
317   Standard_Integer nb = therts.Length();
318   for (Standard_Integer i = 1; i <= nb; i ++) {
319     Standard_Integer j = therts.Value(i);
320     Handle(Standard_Transient) ent = themod->Value(j);
321     Handle(Standard_Transient) res;
322     if (!themap->Search(ent,res)) continue;
323     if (withreports) {
324       Handle(Interface_ReportEntity) rep;
325       if (therep->Search(ent,rep)) res = rep;
326     }
327     iter.GetOneItem(res);
328   }
329   return iter;
330 }
331
332 void Interface_CopyTool::Destroy(){}