b311480e |
1 | // Created on: 1995-06-27 |
2 | // Created by: Jacques GOUSSARD |
3 | // Copyright (c) 1995-1999 Matra Datavision |
973c2be1 |
4 | // Copyright (c) 1999-2014 OPEN CASCADE SAS |
b311480e |
5 | // |
973c2be1 |
6 | // This file is part of Open CASCADE Technology software library. |
b311480e |
7 | // |
d5f74e42 |
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 |
973c2be1 |
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. |
b311480e |
13 | // |
973c2be1 |
14 | // Alternatively, this file may be used under the terms of Open CASCADE |
15 | // commercial license or contractual agreement. |
7fd59977 |
16 | |
42cf5bc1 |
17 | |
7fd59977 |
18 | #include <BRep_Builder.hxx> |
42cf5bc1 |
19 | #include <BRep_Tool.hxx> |
20 | #include <BRepAdaptor_Surface.hxx> |
21 | #include <BRepClass_FaceExplorer.hxx> |
7fd59977 |
22 | #include <BRepLib_MakeFace.hxx> |
ed60a55e |
23 | #include <BRepLib_MakeWire.hxx> |
7fd59977 |
24 | #include <BRepTools.hxx> |
ed60a55e |
25 | #include <BRepTools_WireExplorer.hxx> |
7fd59977 |
26 | #include <BRepTopAdaptor_FClass2d.hxx> |
7fd59977 |
27 | #include <Geom2d_Curve.hxx> |
42cf5bc1 |
28 | #include <gp_Dir2d.hxx> |
7fd59977 |
29 | #include <gp_Pnt2d.hxx> |
30 | #include <gp_Vec2d.hxx> |
7fd59977 |
31 | #include <LocOpe.hxx> |
42cf5bc1 |
32 | #include <LocOpe_SplitShape.hxx> |
33 | #include <Precision.hxx> |
34 | #include <Standard_ConstructionError.hxx> |
7fd59977 |
35 | #include <Standard_ErrorHandler.hxx> |
42cf5bc1 |
36 | #include <Standard_NoSuchObject.hxx> |
37 | #include <StdFail_NotDone.hxx> |
38 | #include <TopExp.hxx> |
39 | #include <TopExp_Explorer.hxx> |
40 | #include <TopoDS.hxx> |
41 | #include <TopoDS_Edge.hxx> |
42 | #include <TopoDS_Face.hxx> |
43 | #include <TopoDS_Iterator.hxx> |
44 | #include <TopoDS_Shape.hxx> |
45 | #include <TopoDS_Vertex.hxx> |
46 | #include <TopoDS_Wire.hxx> |
47 | #include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx> |
48 | #include <TopTools_DataMapIteratorOfDataMapOfShapeShape.hxx> |
49 | #include <TopTools_DataMapOfShapeInteger.hxx> |
50 | #include <TopTools_DataMapOfShapeListOfShape.hxx> |
51 | #include <TopTools_DataMapOfShapeShape.hxx> |
52 | #include <TopTools_IndexedMapOfShape.hxx> |
53 | #include <TopTools_ListIteratorOfListOfShape.hxx> |
54 | #include <TopTools_ListOfShape.hxx> |
55 | #include <TopTools_MapIteratorOfMapOfOrientedShape.hxx> |
56 | #include <TopTools_MapIteratorOfMapOfShape.hxx> |
57 | #include <TopTools_MapOfOrientedShape.hxx> |
58 | #include <TopTools_MapOfShape.hxx> |
b94d4858 |
59 | #include <ShapeAnalysis_Edge.hxx> |
60 | #include <Geom2dAPI_ProjectPointOnCurve.hxx> |
61 | |
62 | #include <Geom_Surface.hxx> |
7fd59977 |
63 | |
64 | static Standard_Boolean IsInside(const TopoDS_Face&, |
65 | const TopoDS_Wire&, |
66 | const TopoDS_Wire&); |
67 | |
68 | static Standard_Boolean IsInside(const TopoDS_Face&, |
69 | const TopoDS_Wire&); |
70 | |
c1e18dd8 |
71 | static void GetDirection(const TopoDS_Edge&, |
72 | const TopoDS_Face&, |
c1e18dd8 |
73 | gp_Pnt2d&, |
aee24cb5 |
74 | gp_Vec2d&, |
75 | Standard_Boolean isFirstEnd); |
c1e18dd8 |
76 | |
aee24cb5 |
77 | static Standard_Boolean ChoixUV(const TopoDS_Edge&, |
7fd59977 |
78 | const TopoDS_Face&, |
c1e18dd8 |
79 | const TopTools_IndexedMapOfShape&, |
80 | TopoDS_Edge&, |
7fd59977 |
81 | gp_Pnt2d&, |
b94d4858 |
82 | gp_Vec2d&); |
7fd59977 |
83 | |
ed60a55e |
84 | static TopoDS_Shape ChooseDirection(const TopoDS_Shape&, |
85 | const TopoDS_Vertex&, |
86 | const TopoDS_Face&, |
87 | const TopTools_ListOfShape&); |
88 | |
7fd59977 |
89 | inline Standard_Boolean SameUV(const gp_Pnt2d& P1, const gp_Pnt2d& P2, |
90 | const BRepAdaptor_Surface& theBAS)//const Standard_Real tol) |
91 | { |
7fd59977 |
92 | Standard_Boolean isSame = Standard_True; |
93 | if(theBAS.IsUPeriodic()) |
94 | isSame = (fabs(P1.X() - P2.X()) < theBAS.UPeriod() *0.5); |
95 | if(theBAS.IsVPeriodic()) |
96 | isSame = (isSame && (fabs(P1.Y() - P2.Y()) < theBAS.VPeriod() *0.5)); |
97 | return isSame; |
98 | //return P1.SquareDistance(P2) < tol * tol; //IFV |
99 | } |
100 | |
101 | |
102 | |
103 | //======================================================================= |
104 | //function : Init |
105 | //purpose : |
106 | //======================================================================= |
107 | |
108 | void LocOpe_SplitShape::Init(const TopoDS_Shape& S) |
109 | { |
110 | myDone = Standard_False; |
111 | myShape = S; |
112 | myDblE.Clear(); |
113 | myMap.Clear(); |
114 | Put(myShape); |
115 | } |
116 | |
117 | |
118 | //======================================================================= |
119 | //function : CanSplit |
120 | //purpose : |
121 | //======================================================================= |
122 | |
123 | Standard_Boolean LocOpe_SplitShape::CanSplit(const TopoDS_Edge& E) const |
124 | { |
125 | if (myDone) { |
126 | return Standard_False; |
127 | } |
128 | if (myMap.IsEmpty()) { |
129 | return Standard_False; |
130 | } |
131 | |
132 | if (!myMap.IsBound(E)) { |
133 | return Standard_False; |
134 | } |
135 | |
136 | // On verifie que l`edge n`appartient pas a un wire deja reconstruit |
137 | TopExp_Explorer exp; |
138 | TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itm(myMap); |
139 | for (; itm.More(); itm.Next()) { |
140 | if (itm.Key().ShapeType() == TopAbs_WIRE && !itm.Value().IsEmpty()) { |
141 | for (exp.Init(itm.Key(),TopAbs_EDGE); exp.More(); exp.Next()) { |
142 | if (exp.Current().IsSame(E)) { |
143 | return Standard_False; |
144 | } |
145 | } |
146 | } |
147 | } |
148 | return Standard_True; |
149 | } |
150 | |
151 | |
152 | //======================================================================= |
153 | //function : Add |
154 | //purpose : |
155 | //======================================================================= |
156 | |
157 | void LocOpe_SplitShape::Add(const TopoDS_Vertex& V, |
158 | const Standard_Real P, |
159 | const TopoDS_Edge& E) |
160 | { |
161 | if (!CanSplit(E)) { |
aee24cb5 |
162 | return; |
7fd59977 |
163 | } |
164 | |
165 | BRep_Builder B; |
166 | TopTools_ListOfShape& le = myMap(E); |
167 | if (le.IsEmpty()) { |
168 | le.Append(E); |
169 | } |
170 | TopTools_ListIteratorOfListOfShape itl(le); |
171 | Standard_Real f,l; |
aee24cb5 |
172 | TopTools_ListOfShape aNewList; |
7fd59977 |
173 | for (; itl.More(); itl.Next()) { |
174 | const TopoDS_Edge& edg = TopoDS::Edge(itl.Value()); |
175 | BRep_Tool::Range(edg,f,l); |
aee24cb5 |
176 | if (P > f + Precision::PConfusion() && P < l - Precision::PConfusion()) { |
7fd59977 |
177 | break; |
aee24cb5 |
178 | |
7fd59977 |
179 | } |
aee24cb5 |
180 | aNewList.Append(edg); |
7fd59977 |
181 | } |
182 | if (!itl.More()) { |
aee24cb5 |
183 | return; |
7fd59977 |
184 | } |
185 | TopoDS_Edge edg = TopoDS::Edge(itl.Value()); |
186 | le.Remove(itl); |
187 | if (V.Orientation() == TopAbs_FORWARD || |
188 | V.Orientation() == TopAbs_REVERSED) { |
189 | |
aee24cb5 |
190 | edg.Orientation(TopAbs_FORWARD); |
191 | TopoDS_Vertex aCurV1, aCurV2; |
192 | TopExp::Vertices(edg, aCurV1, aCurV2); |
193 | Standard_Real aPar1 = BRep_Tool::Parameter(aCurV1,edg); |
194 | |
195 | Standard_Real aPar2 = BRep_Tool::Parameter(aCurV2,edg); |
196 | |
7fd59977 |
197 | TopoDS_Shape aLocalShape = edg.EmptyCopied(); |
198 | TopoDS_Edge E1 = TopoDS::Edge(aLocalShape); |
199 | aLocalShape = edg.EmptyCopied(); |
200 | TopoDS_Edge E2 = TopoDS::Edge(aLocalShape); |
201 | // TopoDS_Edge E1 = TopoDS::Edge(edg.EmptyCopied()); |
202 | // TopoDS_Edge E2 = TopoDS::Edge(edg.EmptyCopied()); |
203 | E1.Orientation(TopAbs_FORWARD); |
204 | E2.Orientation(TopAbs_FORWARD); |
205 | TopoDS_Vertex newVtx = V; |
aee24cb5 |
206 | Standard_Real aTolSplitV = BRep_Tool::Tolerance(V); |
207 | |
208 | aCurV1.Orientation(TopAbs_FORWARD); |
209 | |
210 | B.Add(E1,aCurV1); |
211 | //for degenerated edges tolerance of vertices should be set to maximal value |
212 | //from tolerance of the vertex of the edge and tolerance of splitting vertex |
213 | Standard_Real aTolV1 = ( BRep_Tool::Degenerated(edg) ? |
214 | Max(BRep_Tool::Tolerance(aCurV1), aTolSplitV) : BRep_Tool::Tolerance(aCurV1)); |
215 | |
216 | B.UpdateVertex(aCurV1,aPar1,E1, aTolV1); |
7fd59977 |
217 | newVtx.Orientation(TopAbs_REVERSED); |
218 | B.Add(E1,newVtx); |
219 | B.UpdateVertex(newVtx,P,E1,BRep_Tool::Tolerance(V)); |
220 | newVtx.Orientation(TopAbs_FORWARD); |
221 | B.Add(E2,newVtx); |
222 | B.UpdateVertex(newVtx,P,E2,BRep_Tool::Tolerance(V)); |
aee24cb5 |
223 | |
224 | aCurV2.Orientation(TopAbs_REVERSED); |
225 | B.Add(E2,aCurV2); |
226 | |
227 | //for degenerated edges tolerance of vertices should be set to maximal value |
228 | //from tolerance of the vertex of the edge and tolerance of splitting vertex |
229 | Standard_Real aTolV2 = ( BRep_Tool::Degenerated(edg) ? aTolV1 : BRep_Tool::Tolerance(aCurV2)); |
230 | B.UpdateVertex(aCurV2,aPar2,E2,aTolV2); |
231 | |
232 | aNewList.Append(E1); |
233 | aNewList.Append(E2); |
234 | for (; itl.More(); itl.Next()) |
235 | { |
7856b126 |
236 | const TopoDS_Edge& edg1 = TopoDS::Edge(itl.Value()); |
237 | aNewList.Append(edg1); |
7fd59977 |
238 | } |
aee24cb5 |
239 | myMap.UnBind(E); |
240 | myMap.Bind(E, aNewList); |
241 | |
7fd59977 |
242 | } |
243 | else { |
244 | TopoDS_Shape aLocalShape = edg.EmptyCopied(); |
245 | TopoDS_Edge E1 = TopoDS::Edge(aLocalShape); |
aee24cb5 |
246 | |
7fd59977 |
247 | TopExp_Explorer exp; |
248 | for (exp.Init(edg,TopAbs_VERTEX); exp.More(); exp.Next()) { |
aee24cb5 |
249 | |
7fd59977 |
250 | const TopoDS_Vertex& vtx = TopoDS::Vertex(exp.Current()); |
251 | f = BRep_Tool::Parameter(vtx,edg); |
252 | B.Add(E1,vtx); |
253 | B.UpdateVertex(vtx,f,E1,BRep_Tool::Tolerance(vtx)); |
254 | } |
255 | B.Add(E1,V); |
256 | B.UpdateVertex(V,P,E1,BRep_Tool::Tolerance(V)); |
257 | le.Append(E1); |
258 | } |
259 | } |
260 | |
ed60a55e |
261 | //======================================================================= |
262 | //function : Add |
263 | //purpose : adds the list of wires on the face <F> |
264 | //======================================================================= |
265 | |
aee24cb5 |
266 | Standard_Boolean LocOpe_SplitShape::Add(const TopTools_ListOfShape& Lwires, |
ed60a55e |
267 | const TopoDS_Face& F) |
268 | { |
269 | |
270 | if (myDone) { |
aee24cb5 |
271 | return Standard_False; |
ed60a55e |
272 | } |
273 | |
274 | TopTools_ListOfShape& lf = myMap(F); |
275 | if (lf.IsEmpty()) { |
276 | Rebuild(F); |
277 | } |
278 | |
279 | // On cherche la face descendante de F qui continent le wire |
280 | lf = myMap(F); |
281 | TopTools_ListIteratorOfListOfShape itl(lf); |
282 | TopoDS_Vertex Vfirst,Vlast; |
283 | |
284 | BRepTools::Update(F); |
285 | |
aee24cb5 |
286 | TopTools_ListOfShape aLInside; |
ed60a55e |
287 | for (; itl.More(); itl.Next()) |
288 | { |
289 | const TopoDS_Face& fac = TopoDS::Face(itl.Value()); |
ed60a55e |
290 | TopTools_ListIteratorOfListOfShape itwires(Lwires); |
291 | for (; itwires.More(); itwires.Next()) |
292 | { |
293 | const TopoDS_Wire& aWire = TopoDS::Wire(itwires.Value()); |
aee24cb5 |
294 | if (IsInside(fac, aWire)) |
ed60a55e |
295 | { |
aee24cb5 |
296 | aLInside.Append(aWire); |
297 | |
ed60a55e |
298 | } |
299 | } |
aee24cb5 |
300 | if(aLInside.Extent()) |
ed60a55e |
301 | break; |
302 | } |
aee24cb5 |
303 | if (!aLInside.Extent() || !itl.More()) { |
304 | return Standard_False; |
ed60a55e |
305 | } |
306 | |
307 | TopoDS_Face FaceRef = TopoDS::Face(itl.Value()); |
308 | FaceRef.Orientation(TopAbs_FORWARD); |
309 | lf.Remove(itl); |
310 | |
311 | TopTools_ListOfShape NewWires; |
312 | |
313 | TopTools_DataMapOfShapeInteger SectionsTimes; |
aee24cb5 |
314 | for (itl.Initialize(aLInside); itl.More(); itl.Next()) |
ed60a55e |
315 | SectionsTimes.Bind(itl.Value(), 2); |
316 | |
317 | TopTools_ListOfShape BreakVertices; |
318 | TopTools_ListOfShape BreakOnWires; |
319 | |
320 | TopTools_DataMapOfShapeShape VerWireMap; |
321 | Standard_Integer i; |
322 | TopExp_Explorer ExploF, ExploW; |
aee24cb5 |
323 | for (itl.Initialize(aLInside); itl.More(); itl.Next()) |
ed60a55e |
324 | { |
325 | const TopoDS_Wire& aSection = TopoDS::Wire(itl.Value()); |
326 | TopoDS_Vertex Ver [2]; |
327 | TopExp::Vertices(aSection, Ver[0], Ver[1]); |
328 | for (i = 0; i < 2; i++) |
329 | { |
330 | if (VerWireMap.IsBound(Ver[i])) |
331 | continue; |
332 | for (ExploF.Init(FaceRef, TopAbs_WIRE); ExploF.More(); ExploF.Next()) |
333 | { |
334 | const TopoDS_Shape& aWire = ExploF.Current(); |
335 | TopoDS_Shape aVer; |
336 | for (ExploW.Init(aWire, TopAbs_VERTEX); ExploW.More(); ExploW.Next()) |
337 | { |
338 | aVer = ExploW.Current(); |
339 | if (aVer.IsSame(Ver[i])) |
340 | break; |
341 | } |
342 | if (aVer.IsSame(Ver[i])) |
343 | { |
344 | VerWireMap.Bind(aVer, aWire); |
345 | break; |
346 | } |
347 | } |
348 | } |
349 | } |
350 | |
351 | TopTools_DataMapOfShapeListOfShape VerSecMap; |
aee24cb5 |
352 | for (itl.Initialize(aLInside); itl.More(); itl.Next()) |
ed60a55e |
353 | { |
354 | const TopoDS_Wire& aWire = TopoDS::Wire(itl.Value()); |
355 | TopoDS_Vertex V1, V2; |
356 | TopExp::Vertices(aWire, V1, V2); |
357 | TopTools_ListOfShape LW1, LW2; |
358 | if (!VerSecMap.IsBound(V1)) |
359 | VerSecMap.Bind(V1, LW1); |
360 | VerSecMap(V1).Append(aWire); |
361 | if (!VerSecMap.IsBound(V2)) |
362 | VerSecMap.Bind(V2, LW2); |
363 | VerSecMap(V2).Append(aWire); |
364 | } |
365 | |
366 | //TopTools_IndexedDataMapOfShapeShape InnerTouchingWiresOnVertex; |
367 | |
368 | TopoDS_Wire outerW = BRepTools::OuterWire(FaceRef); |
369 | TopoDS_Wire CurWire = outerW; |
370 | BRepLib_MakeWire *MW; |
371 | MW = new BRepLib_MakeWire(); |
372 | BRepTools_WireExplorer wexp(CurWire, FaceRef); |
373 | for (;;) |
374 | { |
375 | TopoDS_Vertex theStartVertex = wexp.CurrentVertex(), CurVertex; |
376 | TopoDS_Edge CurEdge = wexp.Current(); |
377 | TopoDS_Edge LastEdge = CurEdge; |
378 | MW->Add(CurEdge); |
379 | TopoDS_Wire aSectionWire; |
380 | TopoDS_Vertex aBreakVertex; |
381 | wexp.Next(); |
382 | if (!wexp.More()) |
383 | wexp.Init(CurWire, FaceRef); |
384 | for (;;) |
385 | { |
386 | if (MW->Wire().Closed()) |
387 | break; |
388 | CurVertex = wexp.CurrentVertex(); |
389 | if (VerSecMap.IsBound(CurVertex)) |
390 | { |
391 | TopoDS_Shape aLocalWire = ChooseDirection(LastEdge, CurVertex, FaceRef, VerSecMap(CurVertex)); |
392 | aSectionWire = TopoDS::Wire(aLocalWire); |
393 | break; |
394 | } |
395 | CurEdge = wexp.Current(); |
396 | MW->Add(CurEdge); |
397 | LastEdge = CurEdge; |
398 | wexp.Next(); |
399 | if (!wexp.More()) |
400 | wexp.Init(CurWire, FaceRef); |
401 | } |
402 | if (MW->Wire().Closed()) |
403 | { |
404 | NewWires.Append(MW->Wire()); |
405 | theStartVertex = TopoDS::Vertex(BreakVertices.First()); |
406 | BreakVertices.RemoveFirst(); |
407 | CurWire = TopoDS::Wire(BreakOnWires.First()); |
408 | BreakOnWires.RemoveFirst(); |
409 | wexp.Init(CurWire, FaceRef); |
410 | while (!wexp.CurrentVertex().IsSame(theStartVertex)) |
411 | wexp.Next(); |
412 | MW = new BRepLib_MakeWire(); |
413 | continue; |
414 | } |
415 | aBreakVertex = CurVertex; |
416 | BreakVertices.Append(aBreakVertex); |
417 | BreakOnWires.Append(CurWire); |
418 | for (;;) |
419 | { |
420 | MW->Add(aSectionWire); |
421 | (SectionsTimes(aSectionWire))--; |
422 | if (SectionsTimes(aSectionWire) == 0) |
423 | SectionsTimes.UnBind(aSectionWire); |
424 | if (MW->Wire().Closed()) |
425 | { |
426 | NewWires.Append(MW->Wire()); |
427 | if (SectionsTimes.IsEmpty()) |
428 | break; |
429 | theStartVertex = TopoDS::Vertex(BreakVertices.First()); |
430 | BreakVertices.RemoveFirst(); |
431 | CurWire = TopoDS::Wire(BreakOnWires.First()); |
432 | BreakOnWires.RemoveFirst(); |
433 | wexp.Init(CurWire, FaceRef); |
434 | while (!wexp.CurrentVertex().IsSame(theStartVertex)) |
435 | wexp.Next(); |
436 | MW = new BRepLib_MakeWire(); |
437 | break; |
438 | } |
439 | else |
440 | { |
441 | TopoDS_Vertex V1, V2, aStartVertex; |
442 | TopExp::Vertices(aSectionWire, V1, V2); |
443 | aStartVertex = (V1.IsSame(aBreakVertex))? V2 : V1; |
444 | CurWire = TopoDS::Wire(VerWireMap(aStartVertex)); |
445 | |
446 | wexp.Init(CurWire, FaceRef); |
447 | while (!wexp.CurrentVertex().IsSame(aStartVertex)) |
448 | wexp.Next(); |
449 | |
450 | const TopTools_ListOfShape& Lsections = VerSecMap(aStartVertex); |
451 | if (Lsections.Extent() == 1) |
452 | break; |
453 | |
454 | //else: choose the way |
455 | TopoDS_Wire NextSectionWire = |
456 | TopoDS::Wire((aSectionWire.IsSame(Lsections.First()))? Lsections.Last() : Lsections.First()); |
457 | |
458 | Standard_Integer Times = 0; |
459 | TopTools_DataMapIteratorOfDataMapOfShapeShape itVW(VerWireMap); |
460 | for (; itVW.More(); itVW.Next()) |
461 | if (itVW.Value().IsSame(CurWire)) |
462 | Times++; |
463 | if (Times == 1) //it is inner touching wire |
464 | { |
465 | //InnerTouchingWiresOnVertex.Bind(aWire, aStartVertex); |
466 | } |
467 | else |
468 | { |
469 | //we have to choose the direction |
470 | TopoDS_Edge aStartEdge = wexp.Current(); |
471 | TopTools_ListOfShape Ldirs; |
472 | Ldirs.Append(aStartEdge); |
473 | Ldirs.Append(NextSectionWire); |
474 | TopoDS_Shape theDirection = ChooseDirection(aSectionWire, aStartVertex, FaceRef, Ldirs); |
475 | if (theDirection.IsSame(aStartEdge)) |
476 | break; |
477 | } |
478 | aSectionWire = NextSectionWire; |
479 | aBreakVertex = aStartVertex; |
480 | } //end of else (MW is not closed) |
481 | } //end of for (;;) (loop on section wires) |
482 | if (SectionsTimes.IsEmpty()) |
483 | break; |
484 | } //end of global for (;;) |
485 | |
486 | TopTools_ListOfShape NewFaces; |
487 | BRep_Builder BB; |
488 | for (itl.Initialize(NewWires); itl.More(); itl.Next()) |
489 | { |
490 | TopoDS_Shape aLocalFace = FaceRef.EmptyCopied(); |
491 | TopoDS_Face aNewFace = TopoDS::Face(aLocalFace); |
492 | aNewFace.Orientation(TopAbs_FORWARD); |
493 | BB.Add(aNewFace, itl.Value()); |
494 | NewFaces.Append(aNewFace); |
495 | } |
496 | |
497 | //Inserting holes |
498 | TopTools_ListOfShape Holes; |
499 | for (ExploF.Init(FaceRef, TopAbs_WIRE); ExploF.More(); ExploF.Next()) |
500 | { |
501 | const TopoDS_Shape& aWire = ExploF.Current(); |
502 | ExploW.Init(aWire, TopAbs_EDGE); |
503 | TopoDS_Shape anEdge = ExploW.Current(); |
504 | Standard_Boolean found = Standard_False; |
505 | for (itl.Initialize(NewWires); itl.More(); itl.Next()) |
506 | { |
507 | const TopoDS_Shape& aNewWire = itl.Value(); |
508 | for (ExploW.Init(aNewWire, TopAbs_EDGE); ExploW.More(); ExploW.Next()) |
509 | { |
510 | if (anEdge.IsSame(ExploW.Current())) |
511 | { |
512 | found = Standard_True; |
513 | break; |
514 | } |
515 | } |
516 | if (found) |
517 | break; |
518 | } |
519 | if (!found) |
520 | Holes.Append(aWire); |
521 | } |
522 | TopTools_ListIteratorOfListOfShape itlNewF; |
523 | for (itl.Initialize(Holes); itl.More(); itl.Next()) |
524 | { |
525 | const TopoDS_Wire& aHole = TopoDS::Wire(itl.Value()); |
526 | for (itlNewF.Initialize(NewFaces); itlNewF.More(); itlNewF.Next()) |
527 | { |
528 | TopoDS_Face& aNewFace = TopoDS::Face(itlNewF.Value()); |
529 | if (IsInside(aNewFace, aHole)) |
530 | { |
531 | BB.Add(aNewFace, aHole); |
532 | break; |
533 | } |
534 | } |
535 | } |
536 | |
537 | //Update "myMap" |
538 | lf.Append(NewFaces); |
539 | |
540 | //Update of descendants of wires |
541 | for (ExploF.Init(F, TopAbs_WIRE); ExploF.More(); ExploF.Next()) |
542 | { |
543 | TopTools_ListOfShape& ls = myMap(ExploF.Current()); |
544 | ls.Clear(); |
545 | } |
546 | /////////////////// |
547 | |
548 | // JAG 10.11.95 Codage des regularites |
aee24cb5 |
549 | for (itl.Initialize(aLInside); itl.More(); itl.Next()) |
ed60a55e |
550 | for (ExploW.Init(itl.Value(), TopAbs_EDGE); ExploW.More(); ExploW.Next()) |
551 | { |
552 | const TopoDS_Edge& edg = TopoDS::Edge(ExploW.Current()); |
553 | if (!BRep_Tool::HasContinuity(edg,F,F)) { |
554 | BB.Continuity(edg,F,F,GeomAbs_CN); |
555 | } |
556 | } |
aee24cb5 |
557 | return Standard_True; |
ed60a55e |
558 | } |
7fd59977 |
559 | |
560 | |
561 | //======================================================================= |
562 | //function : Add |
563 | //purpose : |
564 | //======================================================================= |
565 | |
aee24cb5 |
566 | Standard_Boolean LocOpe_SplitShape::Add(const TopoDS_Wire& W, |
7fd59977 |
567 | const TopoDS_Face& F) |
568 | { |
569 | |
570 | if (myDone) { |
aee24cb5 |
571 | return Standard_False; |
7fd59977 |
572 | } |
573 | |
574 | |
575 | TopExp_Explorer exp; |
576 | TopTools_ListOfShape& lf = myMap(F); |
577 | if (lf.IsEmpty()) { |
578 | Rebuild(F); |
579 | } |
580 | try { |
581 | OCC_CATCH_SIGNALS |
582 | if (!LocOpe::Closed(W,F)) { |
aee24cb5 |
583 | if(!AddOpenWire(W,F)) |
584 | return Standard_False; |
7fd59977 |
585 | } |
586 | else { |
aee24cb5 |
587 | if(!AddClosedWire(W,F)) |
588 | return Standard_False; |
7fd59977 |
589 | } |
590 | } catch (Standard_Failure ) { |
0797d9d3 |
591 | #ifdef OCCT_DEBUG |
7fd59977 |
592 | cout << "Warning: SpliShape internal problem detected, some faces may be lost. Check input edges/wires" <<endl; |
593 | #endif |
aee24cb5 |
594 | return Standard_False; |
7fd59977 |
595 | } |
596 | // JAG 10.11.95 Codage des regularites |
597 | BRep_Builder B; |
598 | for (exp.Init(W,TopAbs_EDGE); exp.More(); exp.Next()) { |
599 | const TopoDS_Edge& edg = TopoDS::Edge(exp.Current()); |
600 | if (!BRep_Tool::HasContinuity(edg,F,F)) { |
601 | B.Continuity(edg,F,F,GeomAbs_CN); |
602 | } |
603 | } |
aee24cb5 |
604 | return Standard_True; |
7fd59977 |
605 | } |
606 | |
607 | |
608 | |
609 | //======================================================================= |
610 | //function : AddClosedWire |
611 | //purpose : |
612 | //======================================================================= |
613 | |
aee24cb5 |
614 | Standard_Boolean LocOpe_SplitShape::AddClosedWire(const TopoDS_Wire& W, |
7fd59977 |
615 | const TopoDS_Face& F) |
616 | { |
617 | TopExp_Explorer exp; |
618 | |
619 | // On cherche la face descendante de F qui continent le wire |
620 | TopTools_ListOfShape& lf = myMap(F); |
621 | TopTools_ListIteratorOfListOfShape itl(lf); |
622 | TopoDS_Wire outerW; |
623 | for (; itl.More(); itl.Next()) { |
624 | const TopoDS_Face& fac = TopoDS::Face(itl.Value()); |
aee24cb5 |
625 | |
7fd59977 |
626 | if (IsInside(fac,W)) { |
627 | break; |
628 | } |
629 | |
630 | } |
631 | if (!itl.More()) { |
aee24cb5 |
632 | return Standard_False; |
7fd59977 |
633 | } |
634 | |
635 | BRep_Builder B; |
636 | |
637 | TopAbs_Orientation orWire = W.Orientation(); |
638 | TopoDS_Shape aLocalFace = F.EmptyCopied(); |
639 | TopoDS_Face newFace = TopoDS::Face(aLocalFace); |
640 | // TopoDS_Face newFace = TopoDS::Face(F.EmptyCopied()); |
641 | newFace.Orientation(TopAbs_FORWARD); |
642 | B.Add(newFace,W); |
643 | // GProp_GProps GP; |
644 | // BRepGProp::SurfaceProperties (newFace,GP); |
645 | // if (GP.Mass() < 0) { |
646 | BRepTopAdaptor_FClass2d classif(newFace,Precision::PConfusion()); |
647 | if (classif.PerformInfinitePoint() == TopAbs_IN) { |
648 | //le wire donne defini un trou |
649 | aLocalFace = F.EmptyCopied(); |
650 | newFace = TopoDS::Face(aLocalFace); |
651 | // newFace = TopoDS::Face(F.EmptyCopied()); |
652 | newFace.Orientation(TopAbs_FORWARD); |
653 | orWire = TopAbs::Reverse(orWire); |
654 | B.Add(newFace,W.Oriented(orWire)); |
655 | } |
656 | |
657 | TopoDS_Face FaceRef = TopoDS::Face(itl.Value()); |
658 | FaceRef.Orientation(TopAbs_FORWARD); |
659 | lf.Remove(itl); |
660 | |
661 | aLocalFace = FaceRef.EmptyCopied(); |
662 | TopoDS_Face newRef = TopoDS::Face(aLocalFace); |
663 | // TopoDS_Face newRef = TopoDS::Face(FaceRef.EmptyCopied()); |
664 | newRef.Orientation(TopAbs_FORWARD); |
665 | |
666 | // On suppose que les edges du wire ont des courbes 2d. |
667 | // Comme on ne change pas de surface de base, pas besoin d`UpdateEdge. |
668 | |
669 | for (exp.Init(FaceRef.Oriented(TopAbs_FORWARD),TopAbs_WIRE); |
670 | exp.More(); exp.Next()) { |
671 | const TopoDS_Wire& wir = TopoDS::Wire(exp.Current()); |
672 | if (IsInside(F,wir,W)) { |
673 | B.Add(newFace,wir); |
674 | } |
675 | else { |
676 | B.Add(newRef,wir); |
677 | } |
678 | } |
679 | B.Add(newRef,W.Oriented(TopAbs::Reverse(orWire))); |
680 | lf.Append(newRef); |
681 | lf.Append(newFace); |
aee24cb5 |
682 | return Standard_True; |
7fd59977 |
683 | } |
684 | |
b94d4858 |
685 | //======================================================================= |
686 | //function : checkOverlapping |
687 | //purpose : |
688 | //======================================================================= |
689 | |
690 | static Standard_Boolean checkOverlapping(const TopoDS_Edge& theEdge1, const TopoDS_Edge& theEdge2, |
691 | const TopoDS_Face& theFace) |
692 | { |
693 | |
694 | BRepAdaptor_Surface anAdS(theFace,Standard_False ); |
695 | |
696 | Standard_Real MaxTol = (BRep_Tool::Tolerance(theEdge1) + BRep_Tool::Tolerance(theEdge2)); |
697 | |
698 | Standard_Real aMaxTol2d = Max(anAdS.UResolution(MaxTol),anAdS.VResolution(MaxTol)); |
699 | Standard_Real aTolAng = M_PI/180.; |
700 | Geom2dAPI_ProjectPointOnCurve proj; |
701 | Standard_Real aF1, aL1,aF2, aL2; |
702 | |
703 | Handle(Geom2d_Curve) aCrv1 = BRep_Tool::CurveOnSurface(theEdge1, theFace, aF1, aL1); |
704 | Handle(Geom2d_Curve) aCrv2 = BRep_Tool::CurveOnSurface(theEdge2, theFace, aF2, aL2); |
705 | Standard_Integer j =1, nbP = 4; |
706 | Standard_Real aStep = ( aL2 - aF2)/nbP; |
707 | for( ; j < nbP; j++) |
708 | { |
709 | Standard_Real par2 = aF2 + aStep * j; |
710 | gp_Pnt2d aP2d; |
711 | gp_Vec2d aV2; |
712 | aCrv2->D1(par2, aP2d, aV2); |
713 | |
714 | proj.Init(aP2d,aCrv1, aF1, aL1); |
715 | //check intermediate points |
716 | if(!proj.NbPoints() || proj.LowerDistance() > aMaxTol2d) |
717 | return Standard_False; |
718 | Standard_Real par1 = proj.LowerDistanceParameter(); |
719 | gp_Pnt2d aP2d1; |
720 | gp_Vec2d aV1; |
721 | aCrv1->D1(par1, aP2d1, aV1); |
722 | |
723 | if( !aV1.IsParallel(aV2, aTolAng)) |
724 | return Standard_False; |
725 | } |
726 | return Standard_True; |
727 | |
728 | } |
7fd59977 |
729 | |
730 | //======================================================================= |
731 | //function : AddOpenWire |
732 | //purpose : |
733 | //======================================================================= |
734 | |
aee24cb5 |
735 | Standard_Boolean LocOpe_SplitShape::AddOpenWire(const TopoDS_Wire& W, |
7fd59977 |
736 | const TopoDS_Face& F) |
737 | { |
738 | // On cherche la face descendante de F qui continent le wire |
739 | TopTools_ListOfShape& lf = myMap(F); |
740 | TopTools_ListIteratorOfListOfShape itl(lf); |
741 | TopoDS_Vertex Vfirst,Vlast; |
742 | |
743 | BRepTools::Update(F); |
744 | |
7fd59977 |
745 | Standard_Real tolf, toll, tol1; |
746 | |
747 | TopoDS_Shape aLocalShape = W.Oriented(TopAbs_FORWARD); |
748 | TopExp::Vertices(TopoDS::Wire(aLocalShape),Vfirst,Vlast); |
7fd59977 |
749 | |
750 | tolf = BRep_Tool::Tolerance(Vfirst); |
751 | toll = BRep_Tool::Tolerance(Vlast); |
752 | tol1 = Max(tolf, toll); |
753 | |
754 | |
253881cf |
755 | TopExp_Explorer exp,exp2; |
7fd59977 |
756 | |
757 | TopoDS_Wire wfirst,wlast; |
758 | for (; itl.More(); itl.Next()) { |
253881cf |
759 | TopoDS_Face fac = TopoDS::Face(itl.Value()); |
7fd59977 |
760 | if (!IsInside(fac,W)) { |
761 | continue; |
762 | } |
253881cf |
763 | |
764 | fac.Orientation(TopAbs_FORWARD); |
7fd59977 |
765 | Standard_Boolean ffound = Standard_False; |
766 | Standard_Boolean lfound = Standard_False; |
767 | for (exp.Init(fac,TopAbs_WIRE); exp.More(); exp.Next()) { |
768 | const TopoDS_Wire& wir = TopoDS::Wire(exp.Current()); |
769 | for (exp2.Init(wir,TopAbs_VERTEX); exp2.More(); exp2.Next()) { |
770 | if (!ffound && exp2.Current().IsSame(Vfirst)) { |
771 | ffound = Standard_True; |
772 | wfirst = wir; |
773 | } |
774 | else if (!lfound && exp2.Current().IsSame(Vlast)) { |
775 | lfound = Standard_True; |
776 | wlast = wir; |
777 | } |
778 | if (ffound && lfound) { |
779 | break; |
780 | } |
781 | } |
782 | if (exp2.More()) { |
783 | break; |
784 | } |
785 | } |
786 | if (exp.More()) { |
787 | break; |
788 | } |
789 | } |
790 | if (!itl.More()) { |
aee24cb5 |
791 | return Standard_False; |
7fd59977 |
792 | } |
793 | |
794 | TopoDS_Face FaceRef = TopoDS::Face(itl.Value()); |
795 | FaceRef.Orientation(TopAbs_FORWARD); |
796 | lf.Remove(itl); |
797 | BRep_Builder B; |
798 | |
799 | BRepAdaptor_Surface BAS(FaceRef, Standard_False); |
800 | |
801 | Standard_Boolean IsPeriodic = BAS.IsUPeriodic() || BAS.IsVPeriodic(); |
802 | |
803 | tol1 = Max(BAS.UResolution(tol1), BAS.VResolution(tol1)); |
804 | |
805 | if (wfirst.IsSame(wlast)) { |
806 | // on cree 2 faces en remplacement de itl.Value() |
807 | // Essai JAG |
253881cf |
808 | TopTools_ListOfShape WiresFirst; |
7fd59977 |
809 | for (exp.Init(wfirst,TopAbs_EDGE); exp.More(); exp.Next()) { |
810 | if (BRep_Tool::IsClosed(TopoDS::Edge(exp.Current()),FaceRef)) { |
811 | myDblE.Add(exp.Current()); |
812 | } |
253881cf |
813 | WiresFirst.Append(exp.Current()); |
7fd59977 |
814 | } |
815 | |
816 | TopAbs_Orientation orient; |
817 | TopoDS_Wire newW1,newW2; |
818 | B.MakeWire(newW1); |
819 | newW1.Orientation(TopAbs_FORWARD); |
820 | B.MakeWire(newW2); |
821 | newW2.Orientation(TopAbs_FORWARD); |
822 | |
253881cf |
823 | Standard_Integer nbE = 0; |
7fd59977 |
824 | for (exp.Init(W.Oriented(TopAbs_FORWARD),TopAbs_EDGE); |
825 | exp.More(); exp.Next()) { |
826 | nbE++; |
827 | const TopoDS_Edge& edg = TopoDS::Edge(exp.Current()); |
253881cf |
828 | orient = edg.Orientation(); |
829 | WiresFirst.Append(edg); |
830 | WiresFirst.Append(edg.Oriented(TopAbs::Reverse(orient))); |
831 | myDblE.Add(edg); |
832 | } |
833 | |
c1e18dd8 |
834 | TopTools_IndexedMapOfShape PossE; |
253881cf |
835 | TopTools_MapOfOrientedShape MapE; |
7fd59977 |
836 | TopoDS_Vertex vdeb,vfin; |
837 | Standard_Integer nbPoss; |
838 | |
839 | // On recherche l`edge contenant Vlast |
840 | TopoDS_Edge LastEdge; |
841 | gp_Pnt2d pfirst,plast; |
842 | gp_Vec2d dlast; |
843 | Handle(Geom2d_Curve) C2d; |
844 | Standard_Real f,l; |
845 | |
846 | for (exp.Init(W.Oriented(TopAbs_FORWARD),TopAbs_EDGE); |
847 | exp.More(); exp.Next()) { |
848 | const TopoDS_Edge& edg = TopoDS::Edge(exp.Current()); |
849 | for (exp2.Init(edg,TopAbs_VERTEX); exp2.More(); exp2.Next()) { |
850 | if (exp2.Current().IsSame(Vfirst)) { |
851 | break; |
852 | } |
853 | } |
854 | if (exp2.More()) { |
855 | LastEdge = edg; |
856 | LastEdge.Orientation(edg.Orientation()); |
857 | break; |
858 | } |
859 | } |
860 | |
861 | TopoDS_Shape aLocalFace = FaceRef.Oriented(wfirst.Orientation()); |
862 | C2d = BRep_Tool::CurveOnSurface(LastEdge, TopoDS::Face(aLocalFace), f, l); |
253881cf |
863 | |
7fd59977 |
864 | if (LastEdge.Orientation() == TopAbs_FORWARD) { |
865 | pfirst = C2d->Value(f); |
866 | } |
867 | else { |
868 | pfirst = C2d->Value(l); |
869 | } |
870 | |
871 | for (exp.Init(W.Oriented(TopAbs_FORWARD),TopAbs_EDGE); |
872 | exp.More(); exp.Next()) { |
873 | const TopoDS_Edge& edg = TopoDS::Edge(exp.Current()); |
874 | if( nbE>1 && edg.IsSame(LastEdge) ) |
875 | continue; |
876 | for (exp2.Init(edg,TopAbs_VERTEX); exp2.More(); exp2.Next()) { |
877 | if (exp2.Current().IsSame(Vlast)) { |
878 | break; |
879 | } |
880 | } |
881 | if (exp2.More()) { |
882 | LastEdge = edg; |
883 | LastEdge.Orientation(edg.Orientation()); |
884 | break; |
885 | } |
886 | } |
887 | aLocalFace = FaceRef.Oriented(wfirst.Orientation()); |
aee24cb5 |
888 | GetDirection(LastEdge, TopoDS::Face(aLocalFace),plast , dlast, Standard_False); |
889 | |
7fd59977 |
890 | Standard_Boolean cond; |
891 | |
892 | if(IsPeriodic) { |
893 | |
894 | cond = !(Vfirst.IsSame(Vlast) && SameUV(pfirst,plast,BAS)); |
895 | } |
896 | else { |
897 | cond = !(Vfirst.IsSame(Vlast)); |
898 | } |
253881cf |
899 | |
900 | while (cond) { |
7fd59977 |
901 | PossE.Clear(); |
902 | |
253881cf |
903 | // On enchaine par la fin |
904 | TopTools_ListIteratorOfListOfShape lexp(WiresFirst); |
905 | for (; lexp.More(); lexp.Next()) { |
906 | const TopoDS_Edge& edg = TopoDS::Edge(lexp.Value()); |
7fd59977 |
907 | |
908 | orient = edg.Orientation(); |
909 | TopExp::Vertices(edg,vdeb,vfin); |
aee24cb5 |
910 | |
911 | if ((orient == TopAbs_FORWARD && Vlast.IsSame(vdeb)) || |
912 | (orient == TopAbs_REVERSED && Vlast.IsSame(vfin))) |
913 | PossE.Add(edg); |
7fd59977 |
914 | } |
915 | nbPoss = PossE.Extent(); |
253881cf |
916 | if (nbPoss == 0) |
917 | { |
918 | break; |
919 | } |
920 | |
c1e18dd8 |
921 | TopoDS_Edge aNextEdge; |
7fd59977 |
922 | if (nbPoss == 1) { |
c1e18dd8 |
923 | aNextEdge = TopoDS::Edge (PossE.FindKey (1)); |
51740958 |
924 | TopoDS_Shape aLocalFaceTemp = FaceRef.Oriented(wfirst.Orientation()); |
aee24cb5 |
925 | GetDirection(aNextEdge, TopoDS::Face(aLocalFaceTemp),plast , dlast, Standard_False); |
926 | |
7fd59977 |
927 | } |
928 | else if (nbPoss > 1) { |
929 | // Faire choix en U,V... |
51740958 |
930 | TopoDS_Shape aLocalFaceTemp = FaceRef.Oriented(wfirst.Orientation()); |
7fd59977 |
931 | |
aee24cb5 |
932 | if(!ChoixUV(LastEdge, TopoDS::Face(aLocalFaceTemp), PossE, |
b94d4858 |
933 | aNextEdge, plast, dlast)) |
aee24cb5 |
934 | return Standard_False; |
935 | |
7fd59977 |
936 | } |
937 | |
938 | if (nbPoss >= 1) { |
c1e18dd8 |
939 | if (aNextEdge.IsNull()) |
940 | { |
941 | // loop is not closed. Split is not possible |
aee24cb5 |
942 | return Standard_False; |
c1e18dd8 |
943 | } |
944 | |
945 | if (MapE.Contains(aNextEdge)) |
253881cf |
946 | break; |
c1e18dd8 |
947 | B.Add(newW1, aNextEdge); |
948 | MapE.Add(aNextEdge); |
949 | LastEdge = aNextEdge; |
253881cf |
950 | |
7fd59977 |
951 | if (LastEdge.Orientation() == TopAbs_FORWARD) { |
952 | Vlast = TopExp::LastVertex(LastEdge); |
953 | } |
954 | else { |
955 | Vlast = TopExp::FirstVertex(LastEdge); |
956 | } |
957 | |
958 | toll = BRep_Tool::Tolerance(Vlast); |
959 | tol1 = Max(tolf, toll); |
960 | |
961 | } |
962 | //MODIFICATION PIERRE SMEYERS : si pas de possibilite, on sort avec erreur |
963 | else{ |
964 | cout<<"erreur Spliter : pas de chainage du wire"<<endl; |
aee24cb5 |
965 | return Standard_False; |
7fd59977 |
966 | } |
967 | //fin MODIF. |
968 | |
969 | tol1 = Max(BAS.UResolution(tol1), BAS.VResolution(tol1)); |
970 | |
7fd59977 |
971 | } |
b94d4858 |
972 | |
973 | Standard_Integer nbAddBound =0; |
253881cf |
974 | TopTools_ListIteratorOfListOfShape lexp(WiresFirst); |
b94d4858 |
975 | TopoDS_Shape anE1, anE2; |
253881cf |
976 | for (; lexp.More(); lexp.Next()) { |
977 | const TopoDS_Edge& edg = TopoDS::Edge(lexp.Value()); |
7fd59977 |
978 | if (!MapE.Contains(edg)) { |
979 | B.Add(newW2,edg); |
980 | MapE.Add(edg); |
b94d4858 |
981 | nbAddBound++; |
982 | if(anE1.IsNull()) |
983 | anE1 = edg; |
984 | else |
985 | anE2 = edg; |
986 | |
7fd59977 |
987 | } |
253881cf |
988 | } |
b94d4858 |
989 | //check overlapping edges for second face |
990 | if(nbAddBound <2) |
991 | return Standard_False; |
992 | if(nbAddBound ==2 && !anE1.IsNull() && !anE2.IsNull()) |
993 | { |
994 | if(checkOverlapping(TopoDS::Edge(anE1), TopoDS::Edge(anE2),FaceRef )) |
995 | return Standard_False; |
996 | |
997 | } |
998 | |
999 | nbAddBound =0; |
1000 | |
1001 | TopoDS_Shape anE11, anE12; |
1002 | TopoDS_Iterator anItE(newW1, Standard_False); |
1003 | for( ; anItE.More(); anItE.Next()) |
1004 | { |
1005 | if( anItE.Value().ShapeType() != TopAbs_EDGE) |
1006 | continue; |
1007 | nbAddBound++; |
1008 | if(anE11.IsNull()) |
1009 | anE11 = anItE.Value(); |
1010 | else |
1011 | anE12 = anItE.Value(); |
1012 | |
1013 | } |
1014 | //check overlapping edges for first face |
1015 | if(nbAddBound <2) |
1016 | return Standard_False; |
1017 | if(nbAddBound ==2 && !anE11.IsNull() && !anE12.IsNull()) |
1018 | { |
1019 | if(checkOverlapping(TopoDS::Edge(anE11), TopoDS::Edge(anE12), FaceRef)) |
1020 | return Standard_False; |
1021 | |
1022 | } |
1023 | |
7fd59977 |
1024 | TopoDS_Face newF1,newF2; |
1025 | aLocalFace = FaceRef.EmptyCopied(); |
1026 | newF1 = TopoDS::Face(aLocalFace); |
1027 | newF1.Orientation(TopAbs_FORWARD); |
1028 | aLocalFace = FaceRef.EmptyCopied(); |
1029 | newF2 = TopoDS::Face(aLocalFace); |
7fd59977 |
1030 | newF2.Orientation(TopAbs_FORWARD); |
1031 | |
1032 | // modifs JAG 97.05.28 |
1d47d8d0 |
1033 | |
253881cf |
1034 | B.Add(newF1,newW1); |
1035 | B.Add(newF2,newW2); |
bcf50875 |
1036 | for (exp.Init(FaceRef.Oriented(TopAbs_FORWARD),TopAbs_WIRE); exp.More(); exp.Next()) { |
7fd59977 |
1037 | const TopoDS_Wire& wir = TopoDS::Wire(exp.Current()); |
1038 | if (!wir.IsSame(wfirst)) { |
7fd59977 |
1039 | if (IsInside(newF1, wir)) { |
1040 | B.Add(newF1,wir); |
1041 | } |
1042 | else if (IsInside(newF2, wir)) { |
1043 | B.Add(newF2,wir); |
1044 | } |
1045 | else { |
1046 | // Ce wire est ni dans newF2 ni dans newF1 |
1047 | // Peut etre faut il construire une troisieme face |
1048 | cout << "WARNING: LocOpe_SPlitShape : Ce wire est ni dans newF2 ni dans newF1" << endl; |
1049 | } |
1050 | } |
1051 | } |
1052 | lf.Append(newF1); |
1053 | lf.Append(newF2); |
1054 | |
1055 | // Mise a jour des descendants des wires |
1056 | for (exp.Init(F,TopAbs_WIRE); exp.More(); exp.Next()) { |
1057 | TopTools_ListOfShape& ls = myMap(exp.Current()); |
1058 | itl.Initialize(ls); |
1059 | for (; itl.More(); itl.Next()) { |
1060 | if (itl.Value().IsSame(wfirst)) { |
1061 | break; |
1062 | } |
1063 | } |
1064 | if (itl.More()) { // on a trouve le wire |
1065 | ls.Remove(itl); |
1066 | ls.Append(newW1); |
1067 | ls.Append(newW2); |
1068 | } |
1069 | } |
1070 | } |
1071 | else { |
1072 | // on ne cree qu`une seule face |
1073 | TopoDS_Wire outerW = BRepTools::OuterWire(FaceRef); |
1074 | TopoDS_Wire newWire; |
1075 | TopoDS_Face newFace; |
1076 | B.MakeWire(newWire); |
1077 | newWire.Orientation(TopAbs_FORWARD); |
1078 | TopAbs_Orientation orient,orRelat; |
1079 | |
1080 | if (wfirst.Orientation() == wlast.Orientation()) { |
1081 | orRelat = TopAbs_FORWARD; |
1082 | } |
1083 | else { |
1084 | orRelat = TopAbs_REVERSED; |
1085 | } |
1086 | |
1087 | if (wlast.IsSame(outerW)) { |
1088 | wlast = wfirst; |
1089 | wfirst = outerW; |
1090 | } |
1091 | |
1092 | // Edges de wfirst |
1093 | for (exp.Init(wfirst.Oriented(TopAbs_FORWARD),TopAbs_EDGE); |
1094 | exp.More(); exp.Next()) { |
1095 | B.Add(newWire,TopoDS::Edge(exp.Current())); |
1096 | } |
1097 | |
1098 | // Edges de wlast |
1099 | for (exp.Init(wlast.Oriented(TopAbs_FORWARD),TopAbs_EDGE); |
1100 | exp.More(); exp.Next()) { |
1101 | const TopoDS_Edge& edg = TopoDS::Edge(exp.Current()); |
1102 | orient = TopAbs::Compose(edg.Orientation(),orRelat); |
1103 | B.Add(newWire,edg.Oriented(orient)); |
1104 | } |
1105 | |
1106 | |
1107 | // Edges du wire ajoute, et dans les 2 sens |
1108 | for (exp.Init(W.Oriented(TopAbs_FORWARD),TopAbs_EDGE); |
1109 | exp.More(); exp.Next()) { |
1110 | const TopoDS_Edge& edg = TopoDS::Edge(exp.Current()); |
1111 | orient = edg.Orientation(); |
1112 | B.Add(newWire,edg.Oriented(orient)); |
1113 | B.Add(newWire,edg.Oriented(TopAbs::Reverse(orient))); |
1114 | myDblE.Add(edg.Oriented(orient)); |
1115 | } |
1116 | |
1117 | // on refait une face |
1118 | |
1119 | TopoDS_Shape aLocalFace = FaceRef.EmptyCopied(); |
1120 | newFace = TopoDS::Face(aLocalFace); |
1121 | // newFace = TopoDS::Face(FaceRef.EmptyCopied()); |
1122 | FaceRef.Orientation(TopAbs_FORWARD); |
1123 | for (exp.Init(FaceRef.Oriented(TopAbs_FORWARD),TopAbs_WIRE); |
1124 | exp.More(); exp.Next()) { |
1125 | const TopoDS_Wire& wir = TopoDS::Wire(exp.Current()); |
1126 | if (wir.IsSame(wfirst)) { |
1127 | B.Add(newFace,newWire.Oriented(wir.Orientation())); |
1128 | } |
1129 | else if (!wir.IsSame(wlast)) { |
1130 | B.Add(newFace,wir); |
1131 | } |
1132 | } |
1133 | lf.Append(newFace); |
1134 | |
1135 | // Mise a jour des descendants des wires |
1136 | for (exp.Init(F,TopAbs_WIRE); exp.More(); exp.Next()) { |
1137 | TopTools_ListOfShape& ls = myMap(exp.Current()); |
1138 | itl.Initialize(ls); |
1139 | Standard_Boolean touch = Standard_False; |
1140 | while (itl.More()) { |
1141 | if (itl.Value().IsSame(wfirst) || itl.Value().IsSame(wlast)) { |
1142 | ls.Remove(itl); |
1143 | touch = Standard_True; |
1144 | } |
1145 | else { |
1146 | itl.Next(); |
1147 | } |
1148 | } |
1149 | if (touch) { |
1150 | ls.Append(newWire); |
1151 | } |
1152 | |
1153 | } |
1154 | } |
aee24cb5 |
1155 | return Standard_True; |
7fd59977 |
1156 | } |
1157 | |
1158 | |
1159 | //======================================================================= |
1160 | //function : LeftOf |
1161 | //purpose : |
1162 | //======================================================================= |
1163 | |
1164 | const TopTools_ListOfShape& LocOpe_SplitShape::LeftOf(const TopoDS_Wire& W, |
1165 | const TopoDS_Face& F) |
1166 | { |
1167 | if (myShape.IsNull()) { |
9775fa61 |
1168 | throw Standard_NoSuchObject(); |
7fd59977 |
1169 | } |
1170 | |
1171 | TopExp_Explorer exp,expw,expf; |
1172 | exp.Init(myShape,TopAbs_FACE); |
1173 | for (; exp.More(); exp.Next()) { |
1174 | if (exp.Current().IsSame(F)) { |
1175 | break; |
1176 | } |
1177 | } |
1178 | if (!exp.More()) { |
9775fa61 |
1179 | throw Standard_NoSuchObject(); |
7fd59977 |
1180 | } |
1181 | myLeft.Clear(); |
1182 | |
1183 | const TopoDS_Face& theFace = TopoDS::Face(exp.Current()); |
1184 | TopAbs_Orientation orFace = theFace.Orientation(); |
1185 | TopTools_ListIteratorOfListOfShape itl,itl2; |
1186 | |
1187 | for (expw.Init(W,TopAbs_EDGE); expw.More(); expw.Next()) { |
1188 | const TopoDS_Edge& edg = TopoDS::Edge(expw.Current()); |
1189 | for (itl.Initialize(myMap(theFace)); itl.More(); itl.Next()) { |
1190 | TopoDS_Face fac = TopoDS::Face(itl.Value()); |
1191 | fac.Orientation(orFace); |
1192 | for (expf.Init(fac,TopAbs_EDGE); expf.More(); expf.Next()) { |
1193 | const TopoDS_Edge& edgbis = TopoDS::Edge(expf.Current()); |
1194 | if (edgbis.IsSame(edg) && |
1195 | edgbis.Orientation() == edg.Orientation()) { |
1196 | for (itl2.Initialize(myLeft); itl2.More(); itl2.Next()) { |
1197 | if (itl2.Value().IsSame(fac)) { |
1198 | break; |
1199 | } |
1200 | } |
1201 | if (!itl2.More()) { // la face n`est pas deja presente |
1202 | myLeft.Append(fac); |
1203 | } |
1204 | break; |
1205 | } |
1206 | } |
1207 | if (expf.More()) { // face found |
1208 | break; |
1209 | } |
1210 | } |
1211 | } |
1212 | return myLeft; |
1213 | } |
1214 | |
1215 | |
1216 | //======================================================================= |
1217 | //function : DescendantShapes |
1218 | //purpose : |
1219 | //======================================================================= |
1220 | |
1221 | const TopTools_ListOfShape& LocOpe_SplitShape::DescendantShapes |
1222 | (const TopoDS_Shape& S) |
1223 | { |
1224 | if (!myDone) { |
1225 | Rebuild(myShape); |
1226 | myDone = Standard_True; |
1227 | } |
0797d9d3 |
1228 | #ifdef OCCT_DEBUG |
7fd59977 |
1229 | if (!myDblE.IsEmpty()) { |
1230 | cout << "Le shape comporte des faces invalides" << endl; |
1231 | } |
1232 | #endif |
1233 | return myMap(S); |
1234 | } |
1235 | |
1236 | |
1237 | |
1238 | //======================================================================= |
1239 | //function : Put |
1240 | //purpose : |
1241 | //======================================================================= |
1242 | |
1243 | void LocOpe_SplitShape::Put(const TopoDS_Shape& S) |
1244 | { |
1245 | if (!myMap.IsBound(S)) { |
1246 | TopTools_ListOfShape thelist; |
1247 | myMap.Bind(S, thelist); |
1248 | if (S.ShapeType() != TopAbs_VERTEX) { |
1249 | for(TopoDS_Iterator theIterator(S);theIterator.More(); |
1250 | theIterator.Next()) { |
1251 | Put(theIterator.Value()); |
1252 | } |
1253 | } |
1254 | else { |
1255 | myMap(S).Append(S); |
1256 | } |
1257 | } |
1258 | } |
1259 | |
b94d4858 |
1260 | static void updateToleraces(const TopoDS_Face& theFace, const TopTools_DataMapOfShapeListOfShape& theMap) |
1261 | { |
1262 | TopExp_Explorer aExpE(theFace, TopAbs_EDGE); |
1263 | for (; aExpE.More(); aExpE.Next()) |
1264 | { |
1265 | if (!theMap.IsBound(aExpE.Current())) |
1266 | continue; |
1267 | const TopTools_ListOfShape& lEdges = theMap(aExpE.Current()); |
1268 | if (lEdges.Extent() <= 1) |
1269 | continue; |
1270 | |
1271 | TopTools_ListIteratorOfListOfShape itrE(lEdges); |
1272 | ShapeAnalysis_Edge aSae; |
1273 | |
1274 | for (; itrE.More(); itrE.Next()) |
1275 | { |
1276 | TopoDS_Edge aCurE = TopoDS::Edge(itrE.Value()); |
1277 | Standard_Real amaxdev = 0.; |
1278 | if (aSae.CheckSameParameter(aCurE, theFace, amaxdev)) |
1279 | { |
1280 | BRep_Builder aB; |
1281 | aB.UpdateEdge(aCurE, amaxdev); |
1282 | } |
1283 | } |
1284 | } |
7fd59977 |
1285 | |
b94d4858 |
1286 | } |
7fd59977 |
1287 | //======================================================================= |
1288 | //function : Rebuild |
1289 | //purpose : |
1290 | //======================================================================= |
1291 | |
1292 | Standard_Boolean LocOpe_SplitShape::Rebuild(const TopoDS_Shape& S) |
1293 | |
1294 | { |
b94d4858 |
1295 | if (S.ShapeType() == TopAbs_FACE) |
1296 | updateToleraces(TopoDS::Face(S), myMap); |
7fd59977 |
1297 | TopTools_ListIteratorOfListOfShape itr(myMap(S)); |
1298 | if (itr.More()) { |
1299 | if (itr.Value().IsSame(S)) { |
1300 | return Standard_False; |
1301 | } |
1302 | return Standard_True; |
1303 | } |
1304 | Standard_Boolean rebuild = Standard_False; |
1305 | TopoDS_Iterator it; |
1306 | for(it.Initialize(S); it.More(); it.Next()) { |
1307 | rebuild = Rebuild(it.Value()) || rebuild; |
1308 | } |
1309 | |
1310 | if (rebuild) { |
1311 | BRep_Builder B; |
1312 | TopoDS_Shape result = S.EmptyCopied(); |
1313 | TopAbs_Orientation orient; |
1314 | for(it.Initialize(S); it.More(); it.Next()) { |
1315 | orient = it.Value().Orientation(); |
1316 | for (itr.Initialize(myMap(it.Value())); itr.More(); itr.Next()) { |
1317 | B.Add(result,itr.Value().Oriented(orient)); |
1318 | } |
1319 | } |
da72a17c |
1320 | // Assign "Closed" flag for Wires and Shells only |
1321 | if (result.ShapeType() == TopAbs_WIRE || result.ShapeType() == TopAbs_SHELL) |
1322 | result.Closed (BRep_Tool::IsClosed(result)); |
7fd59977 |
1323 | myMap(S).Append(result); |
1324 | } |
1325 | else { |
1326 | myMap(S).Append(S); |
1327 | } |
1328 | return rebuild; |
1329 | } |
1330 | |
1331 | |
1332 | |
1333 | //======================================================================= |
1334 | //function : IsInside |
1335 | //purpose : |
1336 | //======================================================================= |
1337 | |
1338 | static Standard_Boolean IsInside(const TopoDS_Face& F, |
1339 | const TopoDS_Wire& W1, |
1340 | const TopoDS_Wire& W2) |
1341 | { |
1342 | // Attention, c`est tres boeuf !!!! |
1343 | BRep_Builder B; |
1344 | TopoDS_Shape aLocalShape = F.EmptyCopied(); |
1345 | TopoDS_Face newFace = TopoDS::Face(aLocalShape); |
1346 | // TopoDS_Face newFace = TopoDS::Face(F.EmptyCopied()); |
6e6cd5d9 |
1347 | |
1348 | //TopAbs_Orientation orWire = W2.Orientation(); |
1349 | |
7fd59977 |
1350 | newFace.Orientation(TopAbs_FORWARD); |
1351 | B.Add(newFace,W2); |
1352 | // GProp_GProps GP; |
1353 | // BRepGProp::SurfaceProperties(newFace,GP); |
1354 | // if (GP.Mass() < 0) { |
1355 | BRepTopAdaptor_FClass2d classif(newFace,Precision::PConfusion()); |
1356 | Standard_Boolean Reversed = Standard_False; |
1357 | if (classif.PerformInfinitePoint() == TopAbs_IN) { |
1358 | //le wire donne defini un trou |
1359 | // newFace = TopoDS::Face(F.EmptyCopied()); |
1360 | // newFace.Orientation(TopAbs_FORWARD); |
1361 | // orWire = TopAbs::Reverse(orWire); |
1362 | // B.Add(newFace,W2.Oriented(orWire)); |
1363 | Reversed = Standard_True; |
1364 | } |
1365 | |
1366 | // Standard_Real U,V; |
1367 | TopExp_Explorer exp(W1,TopAbs_EDGE); |
1368 | const TopoDS_Edge& edg = TopoDS::Edge(exp.Current()); |
1369 | TopExp_Explorer exp2(edg,TopAbs_VERTEX); |
1370 | const TopoDS_Vertex& vtx = TopoDS::Vertex(exp2.Current()); |
1371 | Standard_Real prm = BRep_Tool::Parameter(vtx,edg); |
1372 | Standard_Real f,l; |
1373 | Handle(Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface(edg,F,f,l); |
1374 | if(C2d.IsNull()) { |
0797d9d3 |
1375 | #ifdef OCCT_DEBUG |
7fd59977 |
1376 | cout << "Edge is not on surface" <<endl; |
1377 | #endif |
1378 | return Standard_False; |
1379 | } |
1380 | gp_Pnt2d pt2d(C2d->Value(prm)); |
1381 | // BRepClass_FaceClassifier classif(newFace,pt2d,Precision::PConfusion()); |
1382 | // return (classif.State() == TopAbs_IN); |
1383 | if (!Reversed) { |
1384 | return (classif.Perform(pt2d) == TopAbs_IN); |
1385 | } |
1386 | else { |
1387 | return (classif.Perform(pt2d) == TopAbs_OUT); |
1388 | } |
1389 | } |
1390 | |
1391 | |
1392 | //======================================================================= |
1393 | //function : IsInside |
1394 | //purpose : |
1395 | //======================================================================= |
1396 | |
1397 | static Standard_Boolean IsInside(const TopoDS_Face& F, |
1398 | const TopoDS_Wire& W) |
1399 | { |
1400 | // Attention, c`est tres boeuf !!!! |
1401 | TopExp_Explorer exp(W,TopAbs_EDGE); |
1402 | for( ; exp.More(); exp.Next()) { |
1403 | const TopoDS_Edge& edg = TopoDS::Edge(exp.Current()); |
1404 | // TopExp_Explorer exp2(edg,TopAbs_VERTEX); |
1405 | // const TopoDS_Vertex& vtx = TopoDS::Vertex(exp2.Current()); |
1406 | // Standard_Real prm = BRep_Tool::Parameter(vtx,edg); |
1407 | Standard_Real f,l,prm; |
1408 | Handle(Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface(edg,F,f,l); |
1409 | if (!Precision::IsNegativeInfinite(f) && |
1410 | !Precision::IsPositiveInfinite(l)) { |
1411 | prm = (f+l)/2.; |
1412 | } |
1413 | else { |
1414 | if (Precision::IsNegativeInfinite(f) && |
1415 | Precision::IsPositiveInfinite(l)){ |
1416 | prm = 0.; |
1417 | } |
1418 | else if (Precision::IsNegativeInfinite(f)) { |
1419 | prm = l-1.; |
1420 | } |
1421 | else { |
1422 | prm = f+1.; |
1423 | } |
1424 | } |
1425 | |
1426 | gp_Pnt2d pt2d(C2d->Value(prm)); |
1427 | // BRepClass_FaceClassifier classif(F,pt2d,Precision::PConfusion()); |
1428 | // return (classif.State() != TopAbs_OUT); |
1429 | BRepTopAdaptor_FClass2d classif(F,Precision::PConfusion()); |
ed60a55e |
1430 | TopAbs_State stat = classif.Perform(pt2d); |
7fd59977 |
1431 | // return (classif.Perform(pt2d) != TopAbs_OUT); |
1432 | if(stat == TopAbs_OUT) return Standard_False; |
1433 | |
1434 | if(stat == TopAbs_ON) { |
1435 | Standard_Integer nbPnt =10; |
1436 | Standard_Integer nbOut =0,nbIn =0,nbOn=0; |
1437 | Standard_Integer j =1; |
1438 | for( ; j<= nbPnt ; j++) |
1439 | { |
1440 | //check neighbouring point |
1441 | //prm = .66 * prm + .34 * l; |
1442 | prm = f + (l-f)/nbPnt*(j-1); |
1443 | pt2d = C2d->Value(prm); |
1444 | stat = classif.Perform(pt2d); |
1445 | if(stat == TopAbs_OUT ) |
1446 | nbOut++; |
1447 | else if(stat == TopAbs_IN) |
1448 | nbIn++; |
1449 | else |
1450 | nbOn++; |
1451 | } |
1452 | if(nbOut > nbIn + nbOn) |
1453 | return Standard_False; |
1454 | } |
1455 | } |
1456 | return Standard_True; |
1457 | } |
1458 | |
c1e18dd8 |
1459 | //======================================================================= |
1460 | //function : GetDirection |
1461 | //purpose : |
1462 | //======================================================================= |
1463 | static void GetDirection(const TopoDS_Edge& theEdge, |
1464 | const TopoDS_Face& theFace, |
c1e18dd8 |
1465 | gp_Pnt2d& thePnt, |
aee24cb5 |
1466 | gp_Vec2d& theDir, |
1467 | Standard_Boolean isFirstEnd) |
c1e18dd8 |
1468 | { |
1469 | Standard_Real aFirst, aLast; |
1470 | Handle(Geom2d_Curve) aC2d = BRep_Tool::CurveOnSurface (theEdge, theFace, aFirst, aLast); |
1471 | |
1472 | TopAbs_Orientation anOr = theEdge.Orientation(); |
1473 | TopoDS_Vertex aVtx; |
aee24cb5 |
1474 | Standard_Boolean takeFirst = ((anOr == TopAbs_FORWARD && isFirstEnd) || |
1475 | (anOr == TopAbs_REVERSED && !isFirstEnd)); |
1476 | |
1477 | Standard_Real dpar = (aLast - aFirst)*0.01; |
1478 | gp_Pnt2d aP2d; |
1479 | if (takeFirst) |
c1e18dd8 |
1480 | { |
c1e18dd8 |
1481 | aC2d->D0 (aFirst, thePnt); |
aee24cb5 |
1482 | gp_Pnt2d aNextPnt = aC2d->Value(aFirst + dpar); |
1483 | theDir = gp_Vec2d(thePnt, aNextPnt); |
c1e18dd8 |
1484 | } |
c1e18dd8 |
1485 | |
c1e18dd8 |
1486 | else |
1487 | { |
aee24cb5 |
1488 | aC2d->D0 (aLast, thePnt); |
1489 | gp_Pnt2d aPrevPnt = aC2d->Value(aLast - dpar); |
1490 | theDir = gp_Vec2d( aPrevPnt, thePnt ); |
c1e18dd8 |
1491 | } |
aee24cb5 |
1492 | if(anOr == TopAbs_REVERSED) |
1493 | theDir.Reverse(); |
c1e18dd8 |
1494 | } |
7fd59977 |
1495 | |
1496 | //======================================================================= |
1497 | //function : ChoixUV |
1498 | //purpose : |
1499 | //======================================================================= |
1500 | |
aee24cb5 |
1501 | Standard_Boolean ChoixUV(const TopoDS_Edge& Last, |
7fd59977 |
1502 | const TopoDS_Face& F, |
c1e18dd8 |
1503 | const TopTools_IndexedMapOfShape& Poss, |
1504 | TopoDS_Edge& theResEdge, |
7fd59977 |
1505 | gp_Pnt2d& plst, |
b94d4858 |
1506 | gp_Vec2d& dlst) |
7fd59977 |
1507 | { |
7fd59977 |
1508 | gp_Pnt2d p2d; |
1509 | gp_Vec2d v2d; |
c3297e82 |
1510 | gp_Pnt aPCur, aPlst; |
7fd59977 |
1511 | |
1512 | BRepAdaptor_Surface surf(F,Standard_False); // no restriction |
c3297e82 |
1513 | surf.D0 (plst.X(), plst.Y(), aPlst); |
7fd59977 |
1514 | |
7fd59977 |
1515 | gp_Dir2d ref2d(dlst); |
1516 | |
1517 | Handle(Geom2d_Curve) C2d; |
aee24cb5 |
1518 | |
7fd59977 |
1519 | |
1520 | Standard_Integer index = 0, imin=0; |
b94d4858 |
1521 | Standard_Real angmax = -M_PI, ang; |
aee24cb5 |
1522 | |
c1e18dd8 |
1523 | for (index = 1; index <= Poss.Extent(); index++) { |
1524 | TopoDS_Edge anEdge = TopoDS::Edge (Poss.FindKey (index)); |
aee24cb5 |
1525 | |
b94d4858 |
1526 | GetDirection(anEdge, F, p2d, v2d, Standard_True); |
7fd59977 |
1527 | |
c3297e82 |
1528 | surf.D0 (p2d.X(), p2d.Y(), aPCur); |
7fd59977 |
1529 | |
c1e18dd8 |
1530 | if (!Last.IsSame(anEdge)) { |
7fd59977 |
1531 | ang = ref2d.Angle(gp_Dir2d(v2d)); |
1532 | } |
1533 | else { |
c6541a0c |
1534 | ang = -M_PI; |
7fd59977 |
1535 | } |
1536 | |
b94d4858 |
1537 | if ( (ang > angmax)) { |
7fd59977 |
1538 | imin = index; |
7fd59977 |
1539 | angmax = ang; |
1540 | } |
1541 | } |
1542 | |
c1e18dd8 |
1543 | if (imin) |
1544 | { |
1545 | theResEdge = TopoDS::Edge (Poss.FindKey (imin)); |
b94d4858 |
1546 | GetDirection(theResEdge, F, plst, dlst, Standard_False); |
7fd59977 |
1547 | } |
1548 | |
dde68833 |
1549 | return imin != 0; |
7fd59977 |
1550 | } |
ed60a55e |
1551 | |
1552 | //======================================================================= |
1553 | //function : ChooseDirection |
1554 | //purpose : |
1555 | //======================================================================= |
1556 | |
1557 | static TopoDS_Shape ChooseDirection(const TopoDS_Shape& RefDir, |
1558 | const TopoDS_Vertex& RefVertex, |
1559 | const TopoDS_Face& theFace, |
1560 | const TopTools_ListOfShape& Ldirs) |
1561 | { |
1562 | TopExp_Explorer Explo(RefDir, TopAbs_EDGE); |
1563 | TopoDS_Edge RefEdge; |
1564 | TopoDS_Vertex V1, V2; |
1d47d8d0 |
1565 | TopAbs_Orientation anOr = TopAbs_FORWARD; |
ed60a55e |
1566 | for (; Explo.More(); Explo.Next()) |
1567 | { |
1568 | RefEdge = TopoDS::Edge(Explo.Current()); |
1569 | TopExp::Vertices(RefEdge, V1, V2); |
1570 | if (V1.IsSame(RefVertex)) |
1571 | { |
1572 | anOr = TopAbs_REVERSED; |
1573 | break; |
1574 | } |
1575 | else if (V2.IsSame(RefVertex)) |
1576 | { |
1577 | anOr = TopAbs_FORWARD; |
1578 | break; |
1579 | } |
1580 | } |
1581 | |
1582 | Standard_Real RefFirst, RefLast; |
1583 | Handle(Geom2d_Curve) RefCurve = BRep_Tool::CurveOnSurface(RefEdge, theFace, RefFirst, RefLast); |
1584 | gp_Pnt2d RefPnt; |
1585 | gp_Vec2d RefVec; |
1586 | |
1587 | //Standard_Real RefPar = (RefEdge.Orientation() == TopAbs_FORWARD)? RefLast : RefFirst; |
1588 | Standard_Real RefPar = (anOr == TopAbs_FORWARD)? RefLast : RefFirst; |
1589 | RefCurve->D1(RefPar, RefPnt, RefVec); |
1590 | if (anOr == TopAbs_FORWARD) |
1591 | RefVec.Reverse(); |
1592 | |
1593 | Handle(Geom2d_Curve) aCurve; |
1594 | Standard_Real aFirst, aLast, aPar; |
1595 | gp_Vec2d aVec; |
1596 | Standard_Real MinAngle = RealLast(), anAngle; |
1597 | TopoDS_Shape TargetDir; |
1598 | TopTools_ListIteratorOfListOfShape itl(Ldirs); |
1599 | for (; itl.More(); itl.Next()) |
1600 | { |
1601 | const TopoDS_Shape& aShape = itl.Value(); |
1602 | TopoDS_Edge anEdge; |
1603 | for (Explo.Init(aShape, TopAbs_EDGE); Explo.More(); Explo.Next()) |
1604 | { |
1605 | anEdge = TopoDS::Edge(Explo.Current()); |
1606 | TopExp::Vertices(anEdge, V1, V2); |
1607 | if (V1.IsSame(RefVertex)) |
1608 | { |
1609 | anOr = TopAbs_FORWARD; |
1610 | break; |
1611 | } |
1612 | else if (V2.IsSame(RefVertex)) |
1613 | { |
1614 | anOr = TopAbs_REVERSED; |
1615 | break; |
1616 | } |
1617 | } |
1618 | aCurve = BRep_Tool::CurveOnSurface(anEdge, theFace, aFirst, aLast); |
1619 | aPar = (anOr == TopAbs_FORWARD)? aFirst : aLast; |
1620 | aCurve->D1(aPar, RefPnt, aVec); |
1621 | if (anOr == TopAbs_REVERSED) |
1622 | aVec.Reverse(); |
1623 | anAngle = aVec.Angle(RefVec); |
1624 | if (anAngle < 0.) |
1625 | anAngle += 2.*M_PI; |
1626 | |
1627 | if (anAngle < MinAngle) |
1628 | { |
1629 | MinAngle = anAngle; |
1630 | TargetDir = aShape; |
1631 | } |
1632 | } |
1633 | |
1634 | return TargetDir; |
1635 | } |