0022048: Visualization, AIS_InteractiveContext - single object selection should alway...
[occt.git] / src / LocOpe / LocOpe_SplitShape.cxx
CommitLineData
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
64static Standard_Boolean IsInside(const TopoDS_Face&,
65 const TopoDS_Wire&,
66 const TopoDS_Wire&);
67
68static Standard_Boolean IsInside(const TopoDS_Face&,
69 const TopoDS_Wire&);
70
c1e18dd8 71static void GetDirection(const TopoDS_Edge&,
72 const TopoDS_Face&,
c1e18dd8 73 gp_Pnt2d&,
aee24cb5 74 gp_Vec2d&,
75 Standard_Boolean isFirstEnd);
c1e18dd8 76
aee24cb5 77static 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 84static TopoDS_Shape ChooseDirection(const TopoDS_Shape&,
85 const TopoDS_Vertex&,
86 const TopoDS_Face&,
87 const TopTools_ListOfShape&);
88
7fd59977 89inline 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
108void 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
123Standard_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
157void 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 266Standard_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 566Standard_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 614Standard_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
690static 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 735Standard_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
1164const 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
1221const 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
1243void 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 1260static 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
1292Standard_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
1338static 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
1397static 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//=======================================================================
1463static 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 1501Standard_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
1557static 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}