b311480e |
1 | // Created on: 1998-11-26 |
2 | // Created by: Jean-Michel BOULCOURT |
3 | // Copyright (c) 1998-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 | // |
973c2be1 |
8 | // This library is free software; you can redistribute it and / or modify it |
9 | // under the terms of the GNU Lesser General Public version 2.1 as published |
10 | // by the Free Software Foundation, with special exception defined in the file |
11 | // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT |
12 | // distribution for complete text of the license and disclaimer of any warranty. |
b311480e |
13 | // |
973c2be1 |
14 | // Alternatively, this file may be used under the terms of Open CASCADE |
15 | // commercial license or contractual agreement. |
b311480e |
16 | |
7fd59977 |
17 | // Modif : Wed Jan 20 15:40:50 1999. In BuildListResultEdges, we |
18 | // in UpdatePcurve, problem with location of pcurve (mix between loc and locbid) |
19 | // Modif : Thu Jan 21 11:40:20 1999. Add trace context #if DEB |
20 | // add test to avoid loop while in NextConnexEdge (in case of a closed connex wire) |
21 | |
22 | |
23 | #include <BRepLib_FuseEdges.ixx> |
24 | |
25 | #include <TopTools_ListOfShape.hxx> |
26 | #include <TopTools_ListIteratorOfListOfShape.hxx> |
27 | |
28 | #include <TopTools_MapOfShape.hxx> |
29 | |
30 | #include <TopTools_DataMapOfIntegerListOfShape.hxx> |
31 | #include <TopTools_DataMapIteratorOfDataMapOfIntegerListOfShape.hxx> |
32 | |
33 | #include <TopExp.hxx> |
34 | #include <TopExp_Explorer.hxx> |
35 | |
36 | #include <TopoDS.hxx> |
37 | |
38 | #include <BRep_Tool.hxx> |
39 | #include <BRep_Builder.hxx> |
40 | |
41 | |
42 | #include <GeomLib.hxx> |
43 | #include <Geom2d_Curve.hxx> |
44 | #include <Geom_Curve.hxx> |
45 | #include <Geom_BoundedCurve.hxx> |
46 | #include <Geom_Plane.hxx> |
47 | #include <Geom2d_TrimmedCurve.hxx> |
48 | #include <Geom_TrimmedCurve.hxx> |
49 | #include <Geom_Line.hxx> |
50 | #include <Geom_Circle.hxx> |
51 | #include <Geom_Ellipse.hxx> |
52 | #include <Geom_BSplineCurve.hxx> |
53 | #include <Geom_BezierCurve.hxx> |
54 | #include <TColgp_Array1OfPnt.hxx> |
55 | #include <TColStd_Array1OfReal.hxx> |
56 | #include <TColStd_Array1OfInteger.hxx> |
57 | #include <ElCLib.hxx> |
58 | #include <ElSLib.hxx> |
59 | #include <Precision.hxx> |
60 | #include <gp_Pnt2d.hxx> |
61 | #include <gp_Dir2d.hxx> |
62 | #include <gp_Vec2d.hxx> |
63 | #include <gp_Trsf2d.hxx> |
64 | |
65 | #include <BRepTools_Substitution.hxx> |
66 | #include <BRepLib_MakeEdge.hxx> |
67 | #include <BRepLib.hxx> |
68 | #include <TopoDS_Face.hxx> |
69 | #include <TopoDS_Wire.hxx> |
70 | |
71 | #include <Geom2dConvert_CompCurveToBSplineCurve.hxx> |
72 | #include <Geom2d_BSplineCurve.hxx> |
73 | #include <BSplCLib.hxx> |
74 | #include <GeomConvert_CompCurveToBSplineCurve.hxx> |
75 | #include <Extrema_LocateExtPC.hxx> |
76 | #include <GeomAdaptor_Curve.hxx> |
77 | #include <GeomConvert.hxx> |
78 | |
79 | //#ifdef DEB |
80 | //Standard_IMPORT Standard_Boolean TopOpeBRepBuild_GettraceFE(); |
81 | //#endif |
82 | |
83 | static void BCSmoothing(Handle(Geom_BSplineCurve)& theC, |
84 | const Standard_Integer theCont, |
85 | const Standard_Real theTol) |
86 | { |
87 | |
88 | Standard_Integer aNbIter = 5; |
89 | Standard_Boolean bContinue = Standard_True; |
90 | Standard_Integer iter = 1; |
91 | TColStd_SequenceOfInteger aKnotIndex; |
92 | TColStd_SequenceOfReal aKnotIns; |
93 | |
94 | while (bContinue && iter <= aNbIter) { |
95 | |
96 | Standard_Integer aNbKnots = theC->NbKnots(); |
97 | TColStd_Array1OfInteger aMults(1, aNbKnots); |
98 | TColStd_Array1OfReal aKnots(1, aNbKnots); |
99 | |
100 | theC->Multiplicities(aMults); |
101 | theC->Knots(aKnots); |
102 | Standard_Integer i, m = theC->Degree(); |
103 | m = m - theCont; |
104 | |
105 | if(m < 1) return; |
106 | |
107 | aKnotIndex.Clear(); |
108 | |
109 | for(i = 2; i < aNbKnots; i++) { |
110 | if(aMults(i) > m) { |
111 | if(!(theC->RemoveKnot(i, m, theTol))) { |
112 | aKnotIndex.Append(i); |
113 | } |
114 | } |
115 | } |
116 | |
117 | //Prepare knots for inserting; |
118 | |
119 | Standard_Integer aNbAdd = aKnotIndex.Length(); |
120 | |
121 | if(aNbAdd == 0) return; |
122 | |
123 | aKnotIns.Clear(); |
124 | |
125 | Standard_Real aLastKnot = aKnots(1); |
126 | for(i = 1; i <= aNbAdd; i++) { |
127 | |
128 | Standard_Integer anInd = aKnotIndex(i); |
129 | |
130 | Standard_Real aK1 = 0.5*(aKnots(anInd) + aKnots(anInd-1)); |
131 | if(Abs(aK1 - aLastKnot) > 1.e-3) { |
132 | aKnotIns.Append(aK1); |
133 | aLastKnot = aK1; |
134 | } |
135 | |
136 | Standard_Real aK2 = 0.5*(aKnots(anInd+1) + aKnots(anInd)); |
137 | |
138 | if(Abs(aK2 - aLastKnot) > 1.e-3) { |
139 | aKnotIns.Append(aK2); |
140 | aLastKnot = aK2; |
141 | } |
142 | |
143 | } |
144 | |
145 | aNbAdd = aKnotIns.Length(); |
146 | |
147 | for(i = 1; i <= aNbAdd; i++) { |
148 | theC->InsertKnot(aKnotIns(i), m, 1.e-3); |
149 | } |
150 | |
151 | iter++; |
152 | |
153 | } |
154 | |
155 | if(iter > aNbIter) BCSmoothing(theC, theCont, 1.e10); |
156 | |
157 | return; |
158 | } |
159 | |
160 | static void MakeClosedCurve(Handle(Geom_Curve)& C, const gp_Pnt& PF, |
161 | Standard_Real& f, Standard_Real& l) |
162 | { |
163 | Handle(Geom_BSplineCurve) aBC = (*((Handle(Geom_BSplineCurve)*)&C)); |
164 | GeomAbs_Shape aCont = aBC->Continuity(); |
165 | //Find new origin |
166 | aBC->SetPeriodic(); |
167 | Standard_Integer fk = aBC->FirstUKnotIndex(); |
168 | Standard_Integer lk = aBC->LastUKnotIndex(); |
169 | Standard_Integer k; |
170 | Standard_Real eps = Precision::Confusion(); |
171 | eps *= eps; |
172 | Standard_Real porig = 2.*l; |
173 | Standard_Real dmin = 1.e100, pmin = f; |
174 | for(k = fk; k <= lk; k++) { |
175 | gp_Pnt aP = aBC->Value(aBC->Knot(k)); |
176 | Standard_Real d = PF.SquareDistance(aP); |
177 | if(PF.SquareDistance(aP) > eps) { |
178 | if(d < dmin) { |
179 | pmin = aBC->Knot(k); |
180 | dmin = d; |
181 | } |
182 | continue; |
183 | } |
184 | |
185 | porig = aBC->Knot(k); |
186 | break; |
187 | } |
188 | if(porig > l) { |
189 | //try to project |
190 | GeomAdaptor_Curve aGAC(aBC); |
191 | Extrema_LocateExtPC aPrj(PF, aGAC, pmin, Precision::PConfusion()); |
192 | if(aPrj.IsDone()) { |
193 | porig = aPrj.Point().Parameter(); |
194 | } |
195 | else { |
196 | Standard_ConstructionError::Raise("FuseEdges : Projection failed for closed curve"); |
197 | } |
198 | } |
199 | |
200 | aBC->SetOrigin(porig, Precision::PConfusion()); |
201 | f = aBC->FirstParameter(); |
202 | l = aBC->LastParameter(); |
203 | aBC->Segment(f, l); |
204 | if(aCont > GeomAbs_C0 && aBC->Continuity() == GeomAbs_C0) { |
205 | BCSmoothing(aBC, 1, Precision::Confusion()); |
206 | } |
207 | C = aBC; |
208 | f = C->FirstParameter(); |
209 | l = C->LastParameter(); |
210 | } |
211 | |
212 | |
213 | |
214 | //======================================================================= |
215 | //function : BRepLib_FuseEdges |
216 | //purpose : |
217 | //======================================================================= |
218 | |
219 | BRepLib_FuseEdges::BRepLib_FuseEdges(const TopoDS_Shape& theShape, |
220 | // const Standard_Boolean PerformNow) |
221 | const Standard_Boolean ) |
222 | :myShape(theShape),myShapeDone(Standard_False),myEdgesDone(Standard_False), |
223 | myResultEdgesDone(Standard_False),myNbConnexEdge(0), myConcatBSpl(Standard_False) |
224 | { |
225 | // if (theShape.ShapeType() != TopAbs_SHELL && theShape.ShapeType() != TopAbs_SOLID) |
226 | // Standard_ConstructionError::Raise("FuseEdges"); |
227 | Standard_NullObject_Raise_if(theShape.IsNull(),"FuseEdges"); |
228 | myMapFaces.Clear(); |
229 | |
230 | } |
231 | |
232 | //======================================================================= |
233 | //function : AvoidEdges |
234 | //purpose : set edges to avoid being fused |
235 | //======================================================================= |
236 | |
237 | void BRepLib_FuseEdges::AvoidEdges(const TopTools_IndexedMapOfShape& theMapEdg) |
238 | { |
239 | myAvoidEdg = theMapEdg; |
240 | } |
241 | |
242 | //======================================================================= |
243 | //function : SetConcatBSpl |
244 | //purpose : |
245 | //======================================================================= |
246 | |
247 | void BRepLib_FuseEdges::SetConcatBSpl(const Standard_Boolean theConcatBSpl) |
248 | { |
249 | myConcatBSpl = theConcatBSpl; |
250 | } |
251 | |
252 | //======================================================================= |
253 | //function : Edges |
254 | //purpose : returns all the list of edges to be fused each list of the |
255 | // map represent a set of connex edges that can be fused. |
256 | //======================================================================= |
257 | |
258 | void BRepLib_FuseEdges::Edges(TopTools_DataMapOfIntegerListOfShape& theMapLstEdg) |
259 | { |
260 | |
261 | if (!myEdgesDone) { |
262 | BuildListEdges(); |
263 | } |
264 | |
265 | theMapLstEdg = myMapLstEdg; |
266 | } |
267 | |
268 | |
269 | //======================================================================= |
270 | //function : ResultEdges |
271 | //purpose : returns all the fused edges |
272 | //======================================================================= |
273 | |
274 | void BRepLib_FuseEdges::ResultEdges(TopTools_DataMapOfIntegerShape& theMapEdg) |
275 | { |
276 | |
277 | if (!myEdgesDone) { |
278 | BuildListEdges(); |
279 | } |
280 | |
281 | if (!myResultEdgesDone) { |
282 | BuildListResultEdges(); |
283 | } |
284 | |
285 | theMapEdg = myMapEdg; |
286 | } |
287 | |
288 | //======================================================================= |
289 | //function : Faces |
290 | //purpose : returns all the faces that have been modified after perform |
291 | //======================================================================= |
292 | |
293 | void BRepLib_FuseEdges::Faces(TopTools_DataMapOfShapeShape& theMapFac) |
294 | { |
295 | |
296 | if (!myEdgesDone) { |
297 | BuildListEdges(); |
298 | } |
299 | |
300 | if (!myResultEdgesDone) { |
301 | BuildListResultEdges(); |
302 | } |
303 | |
304 | if (!myShapeDone) { |
305 | Perform(); |
306 | } |
307 | |
308 | theMapFac = myMapFaces; |
309 | } |
310 | |
311 | |
312 | //======================================================================= |
313 | //function : NbVertices |
314 | //purpose : |
315 | //======================================================================= |
316 | |
317 | const Standard_Integer BRepLib_FuseEdges::NbVertices() |
318 | { |
319 | |
320 | Standard_NullObject_Raise_if(myShape.IsNull(),"FuseEdges : No Shape"); |
321 | Standard_Integer nbedges, nbvertices = 0; |
322 | |
323 | if (!myEdgesDone) { |
324 | BuildListEdges(); |
325 | } |
326 | |
327 | if ((nbedges = myMapLstEdg.Extent()) > 0) { |
328 | |
329 | TopTools_DataMapIteratorOfDataMapOfIntegerListOfShape itEdg; |
330 | for (itEdg.Initialize(myMapLstEdg); itEdg.More(); itEdg.Next()) { |
331 | const Standard_Integer& iLst = itEdg.Key(); |
332 | const TopTools_ListOfShape& LmapEdg = myMapLstEdg.Find(iLst); |
333 | nbvertices += LmapEdg.Extent() - 1; |
334 | } |
335 | } |
336 | |
337 | return nbvertices; |
338 | |
339 | } |
340 | |
341 | |
342 | //======================================================================= |
343 | //function : Shape |
344 | //purpose : |
345 | //======================================================================= |
346 | |
347 | TopoDS_Shape& BRepLib_FuseEdges::Shape() |
348 | { |
349 | Standard_NullObject_Raise_if(myShape.IsNull(),"FuseEdges : No Shape"); |
350 | |
351 | if (!myEdgesDone) { |
352 | BuildListEdges(); |
353 | } |
354 | |
355 | if (!myResultEdgesDone) { |
356 | BuildListResultEdges(); |
357 | } |
358 | |
359 | if (!myShapeDone) { |
360 | Perform(); |
361 | } |
362 | |
363 | return myShape; |
364 | } |
365 | |
366 | |
367 | |
368 | //======================================================================= |
369 | //function : BuildListEdges |
370 | //purpose : Build the all the lists of edges that are to be fused |
371 | //======================================================================= |
372 | |
373 | void BRepLib_FuseEdges::BuildListEdges() |
374 | { |
375 | |
376 | //#ifdef DEB |
377 | //Standard_Boolean tFE = TopOpeBRepBuild_GettraceFE(); |
378 | //#endif |
379 | |
380 | //#ifdef DEB |
381 | //if (tFE) cout<<endl<<"FuseEdges : BuildListEdges "<<endl; |
382 | //#endif |
383 | |
384 | //-------------------------------------------------------- |
385 | // Step One : Build the map ancestors |
386 | //-------------------------------------------------------- |
387 | |
388 | // Clear the maps |
389 | myMapLstEdg.Clear(); |
390 | myMapVerLstEdg.Clear(); |
391 | myMapEdgLstFac.Clear(); |
392 | |
393 | BuildAncestors(myShape,TopAbs_VERTEX,TopAbs_EDGE,myMapVerLstEdg); |
394 | TopExp::MapShapesAndAncestors(myShape,TopAbs_EDGE,TopAbs_FACE,myMapEdgLstFac); |
395 | |
396 | Standard_Integer iEdg; |
397 | TopTools_MapOfShape mapUniqEdg; |
398 | |
399 | // for each edge of myMapEdgLstFac |
400 | for (iEdg = 1; iEdg <= myMapEdgLstFac.Extent(); iEdg++) { |
401 | const TopoDS_Shape& edgecur = myMapEdgLstFac.FindKey(iEdg); |
402 | TopTools_ListOfShape LstEdg; |
403 | |
404 | // if edge not already treated |
405 | if (!mapUniqEdg.Contains(edgecur) |
406 | && (edgecur.Orientation() == TopAbs_FORWARD ||edgecur.Orientation() == TopAbs_REVERSED) ) { |
407 | if (myAvoidEdg.Contains(edgecur)) |
408 | continue; // edge is not allowed to be fused |
409 | BuildListConnexEdge(edgecur, mapUniqEdg, LstEdg); |
410 | if (LstEdg.Extent() > 1) { |
411 | myNbConnexEdge++; |
412 | myMapLstEdg.Bind(myNbConnexEdge,LstEdg); |
413 | } |
414 | } |
415 | } |
416 | |
417 | myEdgesDone = Standard_True; |
418 | myResultEdgesDone = Standard_False; |
419 | } |
420 | |
421 | |
422 | //======================================================================= |
423 | //function : BuildListResultEdges |
424 | //purpose : Build the result fused edges |
425 | //======================================================================= |
426 | |
427 | void BRepLib_FuseEdges::BuildListResultEdges() |
428 | { |
429 | |
430 | //#ifdef DEB |
431 | //Standard_Boolean tFE = TopOpeBRepBuild_GettraceFE(); |
432 | //#endif |
433 | |
434 | //#ifdef DEB |
435 | //if (tFE) cout<<endl<<"FuseEdges : BuildListResultEdges "<<endl; |
436 | //#endif |
437 | |
438 | // if we have edges to fuse |
439 | if (myMapLstEdg.Extent() > 0) { |
440 | TopTools_DataMapIteratorOfDataMapOfIntegerListOfShape itLstEdg; |
441 | TopoDS_Vertex VF,VL; |
442 | Handle(Geom_Curve) C; |
443 | TopLoc_Location loc; |
444 | Standard_Real f,l; |
445 | TopoDS_Edge NewEdge; |
446 | |
447 | myMapEdg.Clear(); |
448 | |
449 | for (itLstEdg.Initialize(myMapLstEdg); itLstEdg.More(); itLstEdg.Next()) { |
450 | const Standard_Integer& iLst = itLstEdg.Key(); |
451 | const TopTools_ListOfShape& LmapEdg = myMapLstEdg.Find(iLst); |
452 | |
453 | TopoDS_Edge& OldEdge = TopoDS::Edge(LmapEdg.First()); |
454 | |
455 | // the first edge of the list will be replaced by the result fusion edge |
456 | if (OldEdge.Orientation()==TopAbs_REVERSED) { |
457 | VL = TopExp::FirstVertex(TopoDS::Edge(LmapEdg.First()),Standard_True); |
458 | VF = TopExp::LastVertex(TopoDS::Edge(LmapEdg.Last()),Standard_True); |
459 | } |
460 | else { |
461 | VF = TopExp::FirstVertex(TopoDS::Edge(LmapEdg.First()),Standard_True); |
462 | VL = TopExp::LastVertex(TopoDS::Edge(LmapEdg.Last()),Standard_True); |
463 | } |
464 | C = BRep_Tool::Curve(OldEdge,loc,f,l); |
465 | |
466 | if (!loc.IsIdentity()) { |
467 | C = Handle(Geom_Curve)::DownCast(C->Transformed(loc.Transformation())); |
468 | } |
469 | // if the curve is trimmed we get the basis curve to fit the new vertices |
470 | // otherwise the makeedge will fail. |
471 | if (C->DynamicType() == STANDARD_TYPE(Geom_TrimmedCurve)) { |
472 | C = (*((Handle(Geom_TrimmedCurve)*)&C))->BasisCurve(); |
473 | } |
474 | |
475 | if(myConcatBSpl) { |
476 | //Prepare common BSpline curve |
477 | if(C->DynamicType() == STANDARD_TYPE(Geom_BSplineCurve)) { |
478 | TopTools_ListIteratorOfListOfShape anEdgIter(LmapEdg); |
479 | Handle(Geom_TrimmedCurve) aTC = new Geom_TrimmedCurve(C, f, l); |
480 | GeomConvert_CompCurveToBSplineCurve Concat( aTC ); |
481 | |
482 | anEdgIter.Next(); |
483 | for(; anEdgIter.More(); anEdgIter.Next()) { |
484 | Handle(Geom_Curve) aC = BRep_Tool::Curve(TopoDS::Edge(anEdgIter.Value()), f, l); |
485 | aTC = new Geom_TrimmedCurve(aC, f, l); |
486 | if (!Concat.Add(aTC, Precision::Confusion())) { |
487 | // cannot merge curves |
488 | Standard_ConstructionError::Raise("FuseEdges : Concatenation failed"); |
489 | } |
490 | } |
491 | C = Concat.BSplineCurve(); |
492 | } |
493 | } |
494 | |
495 | |
496 | //#ifdef DEB |
497 | //if (tFE) cout<<endl<<"FuseEdges : Creating New Edge "<<endl; |
498 | //#endif |
499 | |
500 | BRepLib_MakeEdge ME; |
501 | |
502 | Standard_Boolean isBSpline = C->DynamicType() == STANDARD_TYPE(Geom_BSplineCurve); |
503 | |
504 | if(VF.IsSame(VL) && isBSpline) { |
505 | //closed edge |
506 | f = C->FirstParameter(); |
507 | l = C->LastParameter(); |
508 | gp_Pnt aPf = C->Value(f); |
509 | gp_Pnt aPl = C->Value(l); |
510 | if(aPf.Distance(aPl) > Precision::Confusion()) { |
511 | Standard_ConstructionError::Raise("FuseEdges : Curve must be closed"); |
512 | } |
513 | gp_Pnt PF = BRep_Tool::Pnt(VF); |
514 | if(PF.Distance(aPf) > Precision::Confusion()) { |
515 | MakeClosedCurve(C, PF, f, l); |
516 | } |
517 | // |
518 | ME.Init(C, VF, VL, f, l); |
519 | if (!ME.IsDone()) { |
520 | Standard_ConstructionError::Raise("FuseEdges : MakeEdge failed for closed curve"); |
521 | } |
522 | } |
523 | else { |
524 | ME.Init(C,VF,VL); |
525 | } |
526 | // BRepLib_MakeEdge ME(C,VF,VL); |
527 | |
528 | if (!ME.IsDone()) { |
529 | // the MakeEdge has fails, one reason could be that the new Vertices are outside |
530 | // the curve which is not infinite and limited to old vertices |
531 | // we try to use ExtendCurveToPoint, then rebuild the NewEdge |
532 | |
533 | //#ifdef DEB |
534 | //if (tFE) cout<<endl<<"FuseEdges : MakeEdge failed. Trying to Extend Curve "<<endl; |
535 | //#endif |
536 | Handle(Geom_BoundedCurve) ExtC = Handle(Geom_BoundedCurve)::DownCast(C->Copy()); |
537 | if (!ExtC.IsNull()) { |
538 | gp_Pnt PF = BRep_Tool::Pnt(VF); |
539 | gp_Pnt PL = BRep_Tool::Pnt(VL); |
540 | GeomLib::ExtendCurveToPoint(ExtC,PF,1,0); |
541 | GeomLib::ExtendCurveToPoint(ExtC,PL,1,1); |
542 | |
543 | ME.Init(ExtC,VF,VL); |
544 | if (!ME.IsDone()) |
545 | Standard_ConstructionError::Raise("FuseEdges : Fusion failed"); |
546 | } |
547 | else |
548 | Standard_ConstructionError::Raise("FuseEdges : Fusion failed"); |
549 | } |
550 | |
551 | NewEdge = ME.Edge(); |
552 | |
553 | //#ifdef DEB |
554 | //if (tFE) cout<<endl<<"FuseEdges : Updating pcurve "<<endl; |
555 | //#endif |
556 | if (UpdatePCurve(OldEdge,NewEdge,LmapEdg)) |
557 | myMapEdg.Bind(iLst,NewEdge); |
558 | } |
559 | |
560 | myResultEdgesDone = Standard_True; |
561 | |
562 | } |
563 | } |
564 | |
565 | //======================================================================= |
566 | //function : Perform |
567 | //purpose : |
568 | //======================================================================= |
569 | |
570 | void BRepLib_FuseEdges::Perform() |
571 | { |
572 | |
573 | //#ifdef DEB |
574 | //Standard_Boolean tFE = TopOpeBRepBuild_GettraceFE(); |
575 | //#endif |
576 | |
577 | if (!myResultEdgesDone) { |
578 | BuildListResultEdges(); |
579 | } |
580 | |
581 | //#ifdef DEB |
582 | //if (tFE) cout<<endl<<"FuseEdges : Perform "<<endl; |
583 | //#endif |
584 | |
585 | // if we have fused edges |
586 | if (myMapEdg.Extent() > 0) { |
587 | TopTools_DataMapIteratorOfDataMapOfIntegerListOfShape itLstEdg; |
588 | TopTools_ListOfShape EmptyList,EdgeToSubs; |
589 | BRepTools_Substitution Bsub; |
590 | |
591 | for (itLstEdg.Initialize(myMapLstEdg); itLstEdg.More(); itLstEdg.Next()) { |
592 | const Standard_Integer& iLst = itLstEdg.Key(); |
593 | if (!myMapEdg.IsBound(iLst)) |
594 | continue; |
595 | const TopTools_ListOfShape& LmapEdg = myMapLstEdg.Find(iLst); |
596 | TopTools_ListIteratorOfListOfShape itEdg; |
597 | |
598 | EdgeToSubs.Clear(); |
599 | TopoDS_Edge& OldEdge = TopoDS::Edge(LmapEdg.First()); |
600 | |
601 | |
602 | EdgeToSubs.Append(myMapEdg(iLst)); |
603 | Bsub.Substitute(OldEdge,EdgeToSubs); |
604 | |
605 | itEdg.Initialize(LmapEdg); |
606 | |
607 | // the other edges of the list will be removed |
608 | while (itEdg.More() ) { |
609 | if (!OldEdge.IsSame(TopoDS::Edge(itEdg.Value()))) { |
610 | Bsub.Substitute(itEdg.Value(),EmptyList); |
611 | } |
612 | itEdg.Next(); |
613 | } |
614 | } |
615 | |
616 | //#ifdef DEB |
617 | //if (tFE) cout<<endl<<"FuseEdges : Building New Shape "<<endl; |
618 | //#endif |
619 | |
620 | // perform the effective substitution |
621 | Bsub.Build(myShape); |
622 | |
623 | // before copying the resulting shape, map the modified faces into myMapFaces |
624 | TopExp_Explorer exp(myShape,TopAbs_FACE); |
625 | |
626 | for (; exp.More(); exp.Next()) { |
627 | const TopoDS_Shape& facecur = exp.Current(); |
628 | if (Bsub.IsCopied(facecur)) { |
629 | myMapFaces.Bind(facecur,(Bsub.Copy(facecur)).First()); |
630 | } |
631 | } |
632 | |
633 | if (Bsub.IsCopied(myShape)) { |
634 | myShape=(Bsub.Copy(myShape)).First(); |
635 | } |
636 | |
637 | //#ifdef DEB |
638 | //if (tFE) cout<<endl<<"FuseEdges : "<< NbVertices() <<" vertices removed"<<endl; |
639 | //#endif |
640 | |
641 | |
642 | } |
643 | |
644 | |
645 | myShapeDone = Standard_True; |
646 | } |
647 | |
648 | |
649 | |
650 | //======================================================================= |
651 | //function : BuildListConnexEdge |
652 | //purpose : giving one edge, build the list of connex edges which have |
653 | // vertices that have only two connex edges. All the edges that are addes |
654 | // to the list must be added also to the mapUniq, in order for the caller |
655 | // to not treat again theses edges. |
656 | // This list is always oriented in the "Forward" direction. |
657 | //======================================================================= |
658 | |
659 | void BRepLib_FuseEdges::BuildListConnexEdge(const TopoDS_Shape& theEdge, |
660 | TopTools_MapOfShape& theMapUniq, |
661 | TopTools_ListOfShape& theLstEdg) |
662 | { |
663 | |
664 | TopoDS_Vertex VF,VL; |
665 | |
666 | |
667 | VL = TopExp::LastVertex(TopoDS::Edge(theEdge),Standard_True); |
668 | TopoDS_Shape edgeconnex; |
669 | TopoDS_Shape edgecur = theEdge; |
670 | theLstEdg.Clear(); |
671 | theLstEdg.Append(edgecur); |
672 | theMapUniq.Add(edgecur); |
673 | TopAbs_Orientation ori2; |
674 | |
675 | // we first build the list of edges connex to edgecur by looking from the last Vertex VL |
676 | while (NextConnexEdge(VL,edgecur,edgeconnex)) { |
677 | if (theMapUniq.Contains(edgeconnex)) { |
678 | break; |
679 | } |
680 | theLstEdg.Append(edgeconnex); |
681 | edgecur = edgeconnex; |
682 | // here take care about internal or external edges. It is non-sense to build |
683 | // the connex list with such edges. |
684 | ori2 = edgecur.Orientation(); |
685 | if (ori2 == TopAbs_EXTERNAL || ori2 == TopAbs_INTERNAL) { |
686 | break; |
687 | } |
688 | VL = TopExp::LastVertex(TopoDS::Edge(edgecur),Standard_True); |
689 | theMapUniq.Add(edgecur); |
690 | } |
691 | |
692 | edgecur = theEdge; |
693 | VF = TopExp::FirstVertex(TopoDS::Edge(theEdge),Standard_True); |
694 | |
695 | // then we build the list of edges connex to edgecur by looking from the first Vertex VF |
696 | while (NextConnexEdge(VF,edgecur,edgeconnex)) { |
697 | if (theMapUniq.Contains(edgeconnex)) { |
698 | break; |
699 | } |
700 | theLstEdg.Prepend(edgeconnex); |
701 | edgecur = edgeconnex; |
702 | // here take care about internal or external edges. It is non-sense to build |
703 | // the connex list with such edges. |
704 | ori2 = edgecur.Orientation(); |
705 | if (ori2 == TopAbs_EXTERNAL || ori2 == TopAbs_INTERNAL) { |
706 | break; |
707 | } |
708 | VF = TopExp::FirstVertex(TopoDS::Edge(edgecur),Standard_True); |
709 | theMapUniq.Add(edgecur); |
710 | } |
711 | |
712 | } |
713 | |
714 | |
715 | //======================================================================= |
716 | //function : NextConnexEdge |
717 | //purpose : Look for an edge connex to theEdge at theVertex. |
718 | // the connex edge must satisfies the following criteria : |
719 | // * theVertex must have exactly 2 connex edges. |
720 | // * the 2 connex edges must have exactly the 2 same connex faces |
721 | // * the 2 connex edges must lie on the same support. |
722 | //======================================================================= |
723 | |
724 | Standard_Boolean BRepLib_FuseEdges::NextConnexEdge(const TopoDS_Vertex& theVertex, |
725 | const TopoDS_Shape& theEdge, |
726 | TopoDS_Shape& theEdgeConnex) const |
727 | { |
728 | |
729 | const TopTools_ListOfShape& LmapEdg = myMapVerLstEdg.FindFromKey(theVertex); |
730 | Standard_Boolean HasConnex = Standard_True; |
731 | TopTools_ListIteratorOfListOfShape itEdg,itFac1,itFac2; |
732 | |
733 | // 1st condition |
734 | if (LmapEdg.Extent() == 2) { |
735 | itEdg.Initialize(LmapEdg); |
736 | theEdgeConnex = itEdg.Value(); |
737 | if (theEdge.IsSame(theEdgeConnex) ) { |
738 | itEdg.Next(); |
739 | theEdgeConnex = itEdg.Value(); |
740 | } |
741 | |
742 | if (myAvoidEdg.Contains(theEdgeConnex)) |
743 | HasConnex = Standard_False; // edge is not allowed to be fused |
744 | |
745 | // 2nd condition |
746 | if (HasConnex) { |
747 | const TopTools_ListOfShape& LmapFac1 = myMapEdgLstFac.FindFromKey(theEdge); |
748 | const TopTools_ListOfShape& LmapFac2 = myMapEdgLstFac.FindFromKey(theEdgeConnex); |
749 | |
750 | if (LmapFac1.Extent() == LmapFac2.Extent() && LmapFac1.Extent() < 3) { |
751 | itFac1.Initialize(LmapFac1); |
752 | |
753 | // for each face in LmapFac1 we look in LmapFac2 if it exists |
754 | while (itFac1.More() && HasConnex) { |
755 | const TopoDS_Shape& face1 = itFac1.Value(); |
756 | for (itFac2.Initialize(LmapFac2); itFac2.More(); itFac2.Next()) { |
757 | const TopoDS_Shape& face2 = itFac2.Value(); |
758 | HasConnex = Standard_False; |
759 | if (face1.IsSame(face2)) { |
760 | HasConnex = Standard_True; |
761 | break; |
762 | } |
763 | } |
764 | itFac1.Next(); |
765 | } |
766 | |
767 | // 3rd condition : same suport |
768 | if (HasConnex) { |
769 | HasConnex = SameSupport(TopoDS::Edge(theEdge),TopoDS::Edge(theEdgeConnex)); |
770 | } |
771 | } |
772 | else |
773 | HasConnex = Standard_False; |
774 | } |
775 | } |
776 | else |
777 | HasConnex = Standard_False; |
778 | |
779 | return HasConnex; |
780 | } |
781 | |
782 | |
783 | |
784 | //======================================================================= |
785 | //function : SameSupport |
786 | //purpose : Edges SameSupport ou pas |
787 | //======================================================================= |
788 | |
789 | Standard_Boolean BRepLib_FuseEdges::SameSupport(const TopoDS_Edge& E1, |
790 | const TopoDS_Edge& E2) const |
791 | { |
792 | |
793 | if (E1.IsNull() || E2.IsNull()) { |
794 | return Standard_False; |
795 | } |
796 | |
797 | |
798 | Handle(Geom_Curve) C1,C2; |
799 | TopLoc_Location loc; |
800 | Standard_Real f1,l1,f2,l2; |
801 | Handle(Standard_Type) typC1,typC2; |
802 | |
803 | C1 = BRep_Tool::Curve(E1,loc,f1,l1); |
804 | //modified by NIZNHY-PKV Mon Nov 15 16:24:10 1999 |
805 | //degenerated edges has no 3D curve |
806 | if(C1.IsNull()) return Standard_False; |
807 | |
808 | if (!loc.IsIdentity()) { |
809 | Handle(Geom_Geometry) GG1 = C1->Transformed(loc.Transformation()); |
810 | C1 = *((Handle(Geom_Curve)*)&GG1); |
811 | } |
812 | C2 = BRep_Tool::Curve(E2,loc,f2,l2); |
813 | //modified by NIZNHY-PKV Mon Nov 15 16:24:38 1999 |
814 | //degenerated edges has no 3D curve |
815 | if(C2.IsNull()) return Standard_False; |
816 | |
817 | if (!loc.IsIdentity()) { |
818 | Handle(Geom_Geometry) GG2 = C2->Transformed(loc.Transformation()); |
819 | C2 = *((Handle(Geom_Curve)*)&GG2); |
820 | } |
821 | |
822 | typC1 = C1->DynamicType(); |
823 | typC2 = C2->DynamicType(); |
824 | |
825 | if (typC1 == STANDARD_TYPE(Geom_TrimmedCurve)) { |
826 | C1 = (*((Handle(Geom_TrimmedCurve)*)&C1))->BasisCurve(); |
827 | typC1 = C1->DynamicType(); |
828 | } |
829 | |
830 | if (typC2 == STANDARD_TYPE(Geom_TrimmedCurve)) { |
831 | C2 = (*((Handle(Geom_TrimmedCurve)*)&C2))->BasisCurve(); |
832 | typC2 = C2->DynamicType(); |
833 | } |
834 | |
835 | if (typC1 != typC2) { |
836 | return Standard_False; |
837 | } |
838 | |
839 | if (typC1 != STANDARD_TYPE(Geom_Line) && |
840 | typC1 != STANDARD_TYPE(Geom_Circle) && |
841 | typC1 != STANDARD_TYPE(Geom_Ellipse) && |
842 | typC1 != STANDARD_TYPE(Geom_BSplineCurve) && |
843 | typC1 != STANDARD_TYPE(Geom_BezierCurve)) { |
844 | #ifdef DEB |
845 | cout << " TopOpeBRepTool_FuseEdge : Type de Support non traite" << endl; |
846 | #endif |
847 | return Standard_False; |
848 | } |
849 | |
850 | // On a presomption de confusion |
851 | const Standard_Real tollin = Precision::Confusion(); |
852 | const Standard_Real tolang = Precision::Angular(); |
853 | if (typC1 == STANDARD_TYPE(Geom_Line)) { |
854 | gp_Lin li1( (*((Handle(Geom_Line)*)&C1))->Lin()); |
855 | gp_Lin li2( (*((Handle(Geom_Line)*)&C2))->Lin()); |
856 | gp_Dir dir1(li1.Direction()); |
857 | gp_Dir dir2(li2.Direction()); |
858 | |
859 | if ( dir1.IsParallel(dir2,tolang) ) { |
860 | // on verifie que l'on n'a pas de cas degenere. Par exemple E1 et E2 connexes |
861 | // mais bouclant l'un sur l'autre (cas tres rare) |
862 | gp_Pnt pf1 = BRep_Tool::Pnt(TopExp::FirstVertex(E1,Standard_True)); |
863 | gp_Pnt pl1 = BRep_Tool::Pnt(TopExp::LastVertex(E1,Standard_True)); |
864 | gp_Pnt pf2 = BRep_Tool::Pnt(TopExp::FirstVertex(E2,Standard_True)); |
865 | gp_Pnt pl2 = BRep_Tool::Pnt(TopExp::LastVertex(E2,Standard_True)); |
866 | if ( pl1.Distance(pf2) < tollin && pl2.Distance(pf1) < tollin) |
867 | return Standard_False; |
868 | else |
869 | return Standard_True; |
870 | } |
871 | return Standard_False; |
872 | } |
873 | else if (typC1 == STANDARD_TYPE(Geom_Circle)) { |
874 | gp_Circ ci1 = (*((Handle(Geom_Circle)*)&C1))->Circ(); |
875 | gp_Circ ci2 = (*((Handle(Geom_Circle)*)&C2))->Circ(); |
876 | if (Abs(ci1.Radius()-ci2.Radius()) <= tollin && |
877 | ci1.Location().SquareDistance(ci2.Location()) <= tollin*tollin && |
878 | ci1.Axis().IsParallel(ci2.Axis(),tolang) ) { |
879 | // Point debut, calage dans periode, et detection meme sens |
880 | return Standard_True; |
881 | } |
882 | return Standard_False; |
883 | } |
884 | else if (typC1 == STANDARD_TYPE(Geom_Ellipse)) { |
885 | gp_Elips ci1 = (*((Handle(Geom_Ellipse)*)&C1))->Elips(); |
886 | gp_Elips ci2 = (*((Handle(Geom_Ellipse)*)&C2))->Elips(); |
887 | |
888 | if (Abs(ci1.MajorRadius()-ci2.MajorRadius()) <= tollin && |
889 | Abs(ci1.MinorRadius()-ci2.MinorRadius()) <= tollin && |
890 | ci1.Location().SquareDistance(ci2.Location()) <= tollin*tollin && |
891 | ci1.Axis().IsParallel(ci2.Axis(),tolang) ) { |
892 | // Point debut, calage dans periode, et detection meme sens |
893 | return Standard_True; |
894 | } |
895 | return Standard_False; |
896 | } |
897 | else if (typC1 == STANDARD_TYPE(Geom_BSplineCurve)) { |
898 | |
899 | if(myConcatBSpl) { |
900 | //Check G1 continuity |
901 | gp_Pnt aPf1, aPl1, aPf2, aPl2; |
902 | gp_Vec aDf1, aDl1, aDf2, aDl2; |
903 | |
904 | C1->D1(f1, aPf1, aDf1); |
905 | C1->D1(l1, aPl1, aDl1); |
906 | |
907 | C2->D1(f2, aPf2, aDf2); |
908 | C2->D1(l2, aPl2, aDl2); |
909 | |
910 | if(aPl1.Distance(aPf2) <= tollin && aDl1.IsParallel(aDf2, tolang)) return Standard_True; |
911 | if(aPl2.Distance(aPf1) <= tollin && aDl2.IsParallel(aDf1, tolang)) return Standard_True; |
912 | if(aPf1.Distance(aPf2) <= tollin && aDf1.IsParallel(aDf2, tolang)) return Standard_True; |
913 | if(aPl1.Distance(aPl2) <= tollin && aDl1.IsParallel(aDl2, tolang)) return Standard_True; |
914 | |
915 | } |
916 | // we must ensure that before fuse two bsplines, the end of one curve does not |
917 | // corresponds to the beginning of the second. |
918 | // we could add a special treatment for periodic bspline. This is not done for the moment. |
919 | if (Abs(f2-l1) > tollin && Abs(f1-l2) > tollin ) { |
920 | return Standard_False; |
921 | } |
922 | |
923 | Handle(Geom_BSplineCurve) B1 = *((Handle(Geom_BSplineCurve)*)&C1); |
924 | Handle(Geom_BSplineCurve) B2 = *((Handle(Geom_BSplineCurve)*)&C2); |
925 | |
926 | Standard_Integer nbpoles = B1->NbPoles(); |
927 | if (nbpoles != B2->NbPoles()) { |
928 | return Standard_False; |
929 | } |
930 | |
931 | Standard_Integer nbknots = B1->NbKnots(); |
932 | if (nbknots != B2->NbKnots()) { |
933 | return Standard_False; |
934 | } |
935 | |
936 | TColgp_Array1OfPnt P1(1, nbpoles), P2(1, nbpoles); |
937 | B1->Poles(P1); |
938 | B2->Poles(P2); |
939 | |
940 | Standard_Real tol3d = BRep_Tool::Tolerance(E1); |
941 | for (Standard_Integer p = 1; p <= nbpoles; p++) { |
942 | if ( (P1(p)).Distance(P2(p)) > tol3d) { |
943 | return Standard_False; |
944 | } |
945 | } |
946 | |
947 | TColStd_Array1OfReal K1(1, nbknots), K2(1, nbknots); |
948 | B1->Knots(K1); |
949 | B2->Knots(K2); |
950 | |
951 | TColStd_Array1OfInteger M1(1, nbknots), M2(1, nbknots); |
952 | B1->Multiplicities(M1); |
953 | B2->Multiplicities(M2); |
954 | |
955 | for (Standard_Integer k = 1; k <= nbknots; k++) { |
956 | if ((K1(k)-K2(k)) > tollin) { |
957 | return Standard_False; |
958 | } |
959 | if (Abs(M1(k)-M2(k)) > tollin) { |
960 | return Standard_False; |
961 | } |
962 | } |
963 | |
964 | if (!B1->IsRational()) { |
965 | if (B2->IsRational()) { |
966 | return Standard_False; |
967 | } |
968 | } |
969 | else { |
970 | if (!B2->IsRational()) { |
971 | return Standard_False; |
972 | } |
973 | } |
974 | |
975 | if (B1->IsRational()) { |
976 | TColStd_Array1OfReal W1(1, nbpoles), W2(1, nbpoles); |
977 | B1->Weights(W1); |
978 | B2->Weights(W2); |
979 | |
980 | for (Standard_Integer w = 1; w <= nbpoles; w++) { |
981 | if (Abs(W1(w)-W2(w)) > tollin) { |
982 | return Standard_False; |
983 | } |
984 | } |
985 | } |
986 | return Standard_True; |
987 | } |
988 | else if (typC1 == STANDARD_TYPE(Geom_BezierCurve)) { |
989 | |
990 | // we must ensure that before fuse two bezier, the end of one curve does not |
991 | // corresponds to the beginning of the second. |
992 | if (Abs(f2-l1) > tollin && Abs(f1-l2) > tollin ) { |
993 | return Standard_False; |
994 | } |
995 | |
996 | Handle(Geom_BezierCurve) B1 = *((Handle(Geom_BezierCurve)*)&C1); |
997 | Handle(Geom_BezierCurve) B2 = *((Handle(Geom_BezierCurve)*)&C2); |
998 | |
999 | Standard_Integer nbpoles = B1->NbPoles(); |
1000 | if (nbpoles != B2->NbPoles()) { |
1001 | return Standard_False; |
1002 | } |
1003 | |
1004 | TColgp_Array1OfPnt P1(1, nbpoles), P2(1, nbpoles); |
1005 | B1->Poles(P1); |
1006 | B2->Poles(P2); |
1007 | |
1008 | for (Standard_Integer p = 1; p <= nbpoles; p++) { |
1009 | if ( (P1(p)).Distance(P2(p)) > tollin) { |
1010 | return Standard_False; |
1011 | } |
1012 | } |
1013 | |
1014 | if (!B1->IsRational()) { |
1015 | if (B2->IsRational()) { |
1016 | return Standard_False; |
1017 | } |
1018 | } |
1019 | else { |
1020 | if (!B2->IsRational()) { |
1021 | return Standard_False; |
1022 | } |
1023 | } |
1024 | |
1025 | if (B1->IsRational()) { |
1026 | TColStd_Array1OfReal W1(1, nbpoles), W2(1, nbpoles); |
1027 | B1->Weights(W1); |
1028 | B2->Weights(W2); |
1029 | |
1030 | for (Standard_Integer w = 1; w <= nbpoles; w++) { |
1031 | if (Abs(W1(w)-W2(w)) > tollin) { |
1032 | return Standard_False; |
1033 | } |
1034 | } |
1035 | } |
1036 | return Standard_True; |
1037 | } |
1038 | return Standard_False; |
1039 | } |
1040 | |
1041 | |
1042 | //======================================================================= |
1043 | //function : BuildAncestors |
1044 | //purpose : This function is like TopExp::MapShapesAndAncestors except |
1045 | // that in the list of shape we do not want duplicate shapes. |
1046 | // if this is useful for other purpose we should create a new method in |
1047 | // TopExp |
1048 | //======================================================================= |
1049 | |
1050 | void BRepLib_FuseEdges::BuildAncestors |
1051 | (const TopoDS_Shape& S, |
1052 | const TopAbs_ShapeEnum TS, |
1053 | const TopAbs_ShapeEnum TA, |
1054 | TopTools_IndexedDataMapOfShapeListOfShape& M) const |
1055 | { |
1056 | |
1057 | TopTools_MapOfShape mapDuplicate; |
1058 | TopTools_ListIteratorOfListOfShape it; |
1059 | Standard_Integer iSh; |
1060 | |
1061 | TopExp::MapShapesAndAncestors(S,TS,TA,M); |
1062 | |
1063 | // for each shape of M |
1064 | for (iSh = 1; iSh <= M.Extent(); iSh++) { |
1065 | TopTools_ListOfShape& Lsh = M(iSh); |
1066 | |
1067 | mapDuplicate.Clear(); |
1068 | // we check for duplicate in the list of Shape |
1069 | it.Initialize(Lsh); |
1070 | while (it.More() ) { |
1071 | if (!mapDuplicate.Contains(it.Value())) { |
1072 | mapDuplicate.Add(it.Value()); |
1073 | it.Next(); |
1074 | } |
1075 | else { |
1076 | Lsh.Remove(it); |
1077 | } |
1078 | } |
1079 | } |
1080 | |
1081 | } |
1082 | |
1083 | |
1084 | //======================================================================= |
1085 | //function : UpdatePCurve |
1086 | //purpose : |
1087 | //======================================================================= |
1088 | |
1089 | Standard_Boolean BRepLib_FuseEdges::UpdatePCurve(const TopoDS_Edge& theOldEdge, |
1090 | TopoDS_Edge& theNewEdge, |
1091 | const TopTools_ListOfShape& theLstEdg) const |
1092 | { |
1093 | |
1094 | |
1095 | // get the pcurve of edge to substitute (theOldEdge) |
1096 | // using CurveOnSurface with Index syntax, so we can update the pcurve |
1097 | // on all the faces |
1098 | BRep_Builder B; |
1099 | Handle(Geom2d_Curve) Curv2d; |
1100 | Handle(Geom_Surface) Surf; |
1101 | TopLoc_Location loc,locbid; |
1102 | Standard_Real ef,el,cf,cl; |
1103 | Standard_Integer iedg = 1; |
1104 | |
1105 | // take care that we want only Pcurve that maps on the surface where the 3D edges lies. |
1106 | const TopTools_ListOfShape& LmapFac = myMapEdgLstFac.FindFromKey(theOldEdge); |
1107 | |
1108 | |
1109 | BRep_Tool::CurveOnSurface(theOldEdge,Curv2d,Surf,loc,cf,cl,iedg); |
1110 | |
1111 | Standard_Boolean pcurveRebuilt = Standard_False; |
1112 | |
1113 | while (!Curv2d.IsNull()) { |
1114 | |
1115 | // we look for a face that contains the same surface as the one that cames |
1116 | // from CurveOnSurface |
1117 | Standard_Boolean SameSurf = Standard_False; |
1118 | TopTools_ListIteratorOfListOfShape itFac; |
1119 | |
1120 | for (itFac.Initialize(LmapFac); itFac.More(); itFac.Next() ) { |
1121 | const TopoDS_Shape& face = itFac.Value(); |
1122 | Handle (Geom_Surface) S = BRep_Tool::Surface(TopoDS::Face(face),locbid); |
1123 | if (S == Surf) { |
1124 | SameSurf = Standard_True; |
1125 | break; |
1126 | } |
1127 | } |
1128 | |
1129 | if (SameSurf) { |
1130 | |
1131 | BRep_Tool::Range(theNewEdge,ef,el); |
1132 | |
1133 | //modified by NIZNHY-PKV Mon Nov 15 14:59:48 1999 _from |
1134 | TopoDS_Edge aFEdge = theOldEdge; |
1135 | aFEdge.Orientation(TopAbs_FORWARD); |
1136 | |
1137 | // take care if the edge is on the closing curve of a closed surface. In that case |
1138 | // we get the second pcurve by reversing the edge and calling again CurveOnSurface method |
1139 | |
1140 | BRep_Tool::CurveOnSurface(aFEdge,Curv2d,Surf,loc,cf,cl,iedg); |
1141 | if (BRep_Tool::IsClosed(theOldEdge,Surf,loc)) { |
1142 | aFEdge.Reverse(); |
1143 | TopoDS_Face aFFace = TopoDS::Face(itFac.Value()); |
1144 | aFFace.Orientation(TopAbs_FORWARD); |
1145 | Handle(Geom2d_Curve) Curv2dR = BRep_Tool::CurveOnSurface(aFEdge, |
1146 | aFFace,cf,cl); |
1147 | if (Curv2d->DynamicType() == STANDARD_TYPE(Geom2d_TrimmedCurve)) |
1148 | Curv2d = (*((Handle(Geom2d_TrimmedCurve)*)&Curv2d))->BasisCurve(); |
1149 | if (Curv2dR->DynamicType() == STANDARD_TYPE(Geom2d_TrimmedCurve)) |
1150 | Curv2dR = (*((Handle(Geom2d_TrimmedCurve)*)&Curv2dR))->BasisCurve(); |
1151 | |
1152 | B.UpdateEdge (theNewEdge,Curv2d,Curv2dR,Surf,loc,BRep_Tool::Tolerance(theNewEdge)); |
1153 | } |
1154 | else { |
1155 | // update the new edge |
1156 | if (Curv2d->DynamicType() == STANDARD_TYPE(Geom2d_TrimmedCurve)) |
1157 | Curv2d = (*((Handle(Geom2d_TrimmedCurve)*)&Curv2d))->BasisCurve(); |
1158 | Standard_Real f, l; |
1159 | f = Curv2d->FirstParameter(); |
1160 | l = Curv2d->LastParameter(); |
1161 | if (l-f + 2.* Epsilon(l-f) < el-ef) |
1162 | { |
1163 | Handle(Geom2d_BoundedCurve) bcurve = Handle(Geom2d_BoundedCurve)::DownCast(Curv2d); |
1164 | if (bcurve.IsNull()) |
1165 | bcurve = new Geom2d_TrimmedCurve( Curv2d, cf, cl ); |
1166 | Geom2dConvert_CompCurveToBSplineCurve Concat( bcurve ); |
1167 | TopTools_ListIteratorOfListOfShape iter( theLstEdg ); |
1168 | iter.Next(); |
1169 | for (; iter.More(); iter.Next()) |
1170 | { |
1171 | TopoDS_Edge& E = TopoDS::Edge(iter.Value()); |
1172 | Standard_Real first, last; |
1173 | Handle(Geom2d_Curve) C = BRep_Tool::CurveOnSurface( E, Surf, loc, first, last ); |
1174 | Handle(Geom2d_BoundedCurve) BC = Handle(Geom2d_BoundedCurve)::DownCast(C); |
1175 | if (BC.IsNull()) |
1176 | BC = new Geom2d_TrimmedCurve( C, first, last ); |
1177 | if (!Concat.Add( BC, Precision::PConfusion() )) |
1178 | // cannot merge pcurves |
1179 | return Standard_False; |
1180 | } |
1181 | Curv2d = Concat.BSplineCurve(); |
1182 | |
1183 | // check that new curve 2d is same range |
1184 | Standard_Real first = Curv2d->FirstParameter(); |
1185 | Standard_Real last = Curv2d->LastParameter(); |
1186 | if (Abs (first - ef) > Precision::PConfusion() || |
1187 | Abs (last - el) > Precision::PConfusion()) |
1188 | { |
1189 | Handle(Geom2d_BSplineCurve) bc = Handle(Geom2d_BSplineCurve)::DownCast(Curv2d); |
1190 | TColStd_Array1OfReal Knots (1, bc->NbKnots()); |
1191 | bc->Knots(Knots); |
1192 | BSplCLib::Reparametrize (ef, el, Knots); |
1193 | bc->SetKnots(Knots); |
1194 | } |
1195 | pcurveRebuilt = Standard_True; |
1196 | } |
1197 | |
1198 | B.UpdateEdge (theNewEdge,Curv2d,Surf,loc,BRep_Tool::Tolerance(theNewEdge)); |
1199 | } |
1200 | |
1201 | // the old pcurve range is cf,cl. The new 3d edge range is ef,el. if we want |
1202 | // the pcurve to be samerange we must adapt the parameter of the edge. In general |
1203 | // cases cf=ef and cl=el expect for periodic curve if the new edge is going over |
1204 | // the value 0. |
1205 | if(!pcurveRebuilt) { |
1206 | if (theOldEdge.Orientation()== TopAbs_REVERSED) { |
1207 | B.Range(theNewEdge,cl-el+ef,cl); |
1208 | } |
1209 | else { |
1210 | B.Range(theNewEdge,cf,cf+el-ef); |
1211 | } |
1212 | } |
1213 | } |
1214 | |
1215 | // get next pcurve |
1216 | iedg++; |
1217 | BRep_Tool::CurveOnSurface(theOldEdge,Curv2d,Surf,loc,cf,cl,iedg); |
1218 | } |
1219 | |
1220 | if (pcurveRebuilt) |
1221 | { |
1222 | // force same parameter |
1223 | B.SameParameter (theNewEdge, Standard_False); |
1224 | BRepLib::SameParameter (theNewEdge, BRep_Tool::Tolerance(theNewEdge)); |
1225 | } |
1226 | |
1227 | return Standard_True; |
1228 | } |
1229 | |
1230 | |