0027021: TopExp::Vertices performance optimization
[occt.git] / src / TopExp / TopExp.cxx
1 // Created on: 1993-01-19
2 // Created by: Remi LEQUETTE
3 // Copyright (c) 1993-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 #define No_Standard_NoMoreObject
18 #define No_Standard_NoSuchObject
19 #define No_Standard_TypeMismatch
20
21
22 #include <TopExp.hxx>
23 #include <TopExp_Explorer.hxx>
24 #include <TopoDS.hxx>
25 #include <TopoDS_Edge.hxx>
26 #include <TopoDS_Iterator.hxx>
27 #include <TopoDS_Shape.hxx>
28 #include <TopoDS_Vertex.hxx>
29 #include <TopoDS_Wire.hxx>
30 #include <TopTools_ListOfShape.hxx>
31 #include <TopTools_MapIteratorOfMapOfShape.hxx>
32 #include <TopTools_MapOfShape.hxx>
33
34 //=======================================================================
35 //function : MapShapes
36 //purpose  : 
37 //=======================================================================
38 void TopExp::MapShapes(const TopoDS_Shape& S,
39                        const TopAbs_ShapeEnum T,
40                        TopTools_IndexedMapOfShape& M)
41 {
42   TopExp_Explorer Ex(S,T);
43   while (Ex.More()) {
44     M.Add(Ex.Current());
45     Ex.Next();
46   }
47 }
48
49 //=======================================================================
50 //function : MapShapes
51 //purpose  : 
52 //=======================================================================
53
54 void TopExp::MapShapes(const TopoDS_Shape& S,
55                        TopTools_IndexedMapOfShape& M)
56 {
57   M.Add(S);
58   TopoDS_Iterator It(S);
59   while (It.More()) {
60     MapShapes(It.Value(),M);
61     It.Next();
62   }
63 }
64
65 //=======================================================================
66 //function : MapShapesAndAncestors
67 //purpose  : 
68 //=======================================================================
69
70 void  TopExp::MapShapesAndAncestors
71   (const TopoDS_Shape& S, 
72    const TopAbs_ShapeEnum TS, 
73    const TopAbs_ShapeEnum TA, 
74    TopTools_IndexedDataMapOfShapeListOfShape& M)
75 {
76   TopTools_ListOfShape empty;
77   
78   // visit ancestors
79   TopExp_Explorer exa(S,TA);
80   while (exa.More()) {
81     // visit shapes
82     const TopoDS_Shape& anc = exa.Current();
83     TopExp_Explorer exs(anc,TS);
84     while (exs.More()) {
85       Standard_Integer index = M.FindIndex(exs.Current());
86       if (index == 0) index = M.Add(exs.Current(),empty);
87       M(index).Append(anc);
88       exs.Next();
89     }
90     exa.Next();
91   }
92   
93   // visit shapes not under ancestors
94   TopExp_Explorer ex(S,TS,TA);
95   while (ex.More()) {
96     Standard_Integer index = M.FindIndex(ex.Current());
97     if (index == 0) index = M.Add(ex.Current(),empty);
98     ex.Next();
99   }
100 }
101
102
103
104 //=======================================================================
105 //function : FirstVertex
106 //purpose  : 
107 //=======================================================================
108
109 TopoDS_Vertex  TopExp::FirstVertex(const TopoDS_Edge& E,
110                                    const Standard_Boolean CumOri)
111 {
112   TopoDS_Iterator ite(E,CumOri);
113   while (ite.More()) {
114     if (ite.Value().Orientation() == TopAbs_FORWARD) 
115       return TopoDS::Vertex(ite.Value());
116     ite.Next();
117   }
118   return TopoDS_Vertex();
119 }
120
121
122 //=======================================================================
123 //function : LastVertex
124 //purpose  : 
125 //=======================================================================
126
127 TopoDS_Vertex  TopExp::LastVertex(const TopoDS_Edge& E,
128                                   const Standard_Boolean CumOri)
129 {
130   TopoDS_Iterator ite(E,CumOri);
131   while (ite.More()) {
132     if (ite.Value().Orientation() == TopAbs_REVERSED) 
133       return TopoDS::Vertex(ite.Value());
134     ite.Next();
135   }
136   return TopoDS_Vertex();
137 }
138
139
140 //=======================================================================
141 //function : Vertices
142 //purpose  : 
143 //=======================================================================
144
145 void  TopExp::Vertices(const TopoDS_Edge& E,
146                        TopoDS_Vertex& Vfirst,
147                        TopoDS_Vertex& Vlast,
148                        const Standard_Boolean CumOri)
149 {
150   // minor optimization for case when Vfirst and Vlast are non-null:
151   // at least for VC++ 10, it is faster if we use boolean flags than 
152   // if we nullify vertices at that point (see #27021)
153   Standard_Boolean isFirstDefined = Standard_False;
154   Standard_Boolean isLastDefined = Standard_False;
155   
156   TopoDS_Iterator ite(E, CumOri);
157   while (ite.More()) {
158     const TopoDS_Shape& aV = ite.Value();
159     if (aV.Orientation() == TopAbs_FORWARD)
160     {
161       Vfirst = TopoDS::Vertex (aV);
162       isFirstDefined = Standard_True;
163     }
164     else if (aV.Orientation() == TopAbs_REVERSED)
165     {
166       Vlast = TopoDS::Vertex (aV);
167       isLastDefined = Standard_True;
168     }
169     ite.Next();
170   }
171
172   if (!isFirstDefined)
173     Vfirst.Nullify();
174
175   if (!isLastDefined)
176     Vlast.Nullify();
177 }
178
179
180 //=======================================================================
181 //function : Vertices
182 //purpose  : 
183 //=======================================================================
184
185 void  TopExp::Vertices(const TopoDS_Wire& W,
186                        TopoDS_Vertex& Vfirst,
187                        TopoDS_Vertex& Vlast)
188 {
189   Vfirst = Vlast = TopoDS_Vertex(); // nullify
190
191   TopTools_MapOfShape vmap;
192   TopoDS_Iterator it(W);
193   TopoDS_Vertex   V1,V2;
194
195   while (it.More()) {
196     const TopoDS_Edge& E = TopoDS::Edge(it.Value());
197     if (E.Orientation() == TopAbs_REVERSED)
198       TopExp::Vertices(E,V2,V1);
199     else
200       TopExp::Vertices(E,V1,V2);
201     // add or remove in the vertex map
202     V1.Orientation(TopAbs_FORWARD);
203     V2.Orientation(TopAbs_REVERSED);
204     if (!vmap.Add(V1)) vmap.Remove(V1);
205     if (!vmap.Add(V2)) vmap.Remove(V2);
206
207     it.Next();
208   }
209   if (vmap.IsEmpty()) { // closed
210     TopoDS_Shape aLocalShape = V2.Oriented(TopAbs_FORWARD);
211     Vfirst = TopoDS::Vertex(aLocalShape);
212     aLocalShape = V2.Oriented(TopAbs_REVERSED);
213     Vlast  = TopoDS::Vertex(aLocalShape);
214 //    Vfirst = TopoDS::Vertex(V2.Oriented(TopAbs_FORWARD));
215 //    Vlast  = TopoDS::Vertex(V2.Oriented(TopAbs_REVERSED));
216   }
217   else if (vmap.Extent() == 2) { //open
218     TopTools_MapIteratorOfMapOfShape ite(vmap);
219     
220     while (ite.More() && ite.Key().Orientation() != TopAbs_FORWARD) 
221       ite.Next();
222     if (ite.More()) Vfirst = TopoDS::Vertex(ite.Key());
223     ite.Initialize(vmap);
224     while (ite.More() && ite.Key().Orientation() != TopAbs_REVERSED) 
225       ite.Next();
226     if (ite.More()) Vlast = TopoDS::Vertex(ite.Key());
227   }
228 }
229
230
231 //=======================================================================
232 //function : CommonVertex
233 //purpose  : 
234 //=======================================================================
235 Standard_Boolean TopExp::CommonVertex(const TopoDS_Edge& E1, 
236                                       const TopoDS_Edge& E2,
237                                       TopoDS_Vertex& V)
238 {
239   TopoDS_Vertex firstVertex1, lastVertex1, firstVertex2, lastVertex2;
240   TopExp::Vertices(E1, firstVertex1, lastVertex1);
241   TopExp::Vertices(E2, firstVertex2, lastVertex2);
242
243   if (firstVertex1.IsSame(firstVertex2) || 
244       firstVertex1.IsSame(lastVertex2)) {
245     V = firstVertex1;
246     return Standard_True;
247   }
248   if (lastVertex1.IsSame(firstVertex2) ||
249            lastVertex1.IsSame(lastVertex2)) {
250     V = lastVertex1;
251     return Standard_True;
252   }
253   return Standard_False;
254 } // CommonVertex
255