1 // Created on: 2000-02-07
2 // Created by: data exchange team
3 // Copyright (c) 2000-2014 OPEN CASCADE SAS
5 // This file is part of Open CASCADE Technology software library.
7 // This library is free software; you can redistribute it and / or modify it
8 // under the terms of the GNU Lesser General Public version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
16 #include <ShapeAlgo_AlgoContainer.ixx>
18 #include <GeomInt_WLApprox.hxx>
19 #include <IntSurf_LineOn2S.hxx>
20 #include <IntSurf_PntOn2S.hxx>
21 #include <IntPatch_WLine.hxx>
23 #include <BRep_Builder.hxx>
24 #include <BRep_Tool.hxx>
25 #include <BRepBuilderAPI_MakeEdge.hxx>
26 #include <BRepBuilderAPI_MakeWire.hxx>
28 #include <TopoDS_Edge.hxx>
29 #include <TopoDS_Wire.hxx>
30 #include <TopoDS_Iterator.hxx>
33 #include <Precision.hxx>
35 #include <TColStd_Array1OfReal.hxx>
36 #include <TColStd_Array1OfInteger.hxx>
37 #include <TColgp_Array1OfPnt.hxx>
38 #include <TColgp_Array1OfPnt2d.hxx>
40 #include <ShapeBuild_Edge.hxx>
41 #include <ShapeConstruct.hxx>
42 #include <ShapeCustom.hxx>
43 #include <ShapeCustom_Surface.hxx>
44 #include <ShapeAnalysis.hxx>
45 #include <ShapeAnalysis_Edge.hxx>
46 #include <ShapeFix.hxx>
47 #include <ShapeFix_Edge.hxx>
48 #include <ShapeUpgrade.hxx>
49 #include <ShapeUpgrade_ShapeDivideContinuity.hxx>
50 #include <ShapeExtend_WireData.hxx>
51 #include <ShapeExtend_WireData.hxx>
54 #include <Precision.hxx>
55 #include <ShapeFix_Wire.hxx>
56 #include <BRepTools.hxx>
58 //=======================================================================
59 //function : ShapeAlgo_AlgoContainer
61 //=======================================================================
63 ShapeAlgo_AlgoContainer::ShapeAlgo_AlgoContainer()
65 myTC = new ShapeAlgo_ToolContainer;
68 //=======================================================================
69 //function : ConnectNextWire
71 //=======================================================================
73 Standard_Boolean ShapeAlgo_AlgoContainer::ConnectNextWire (const Handle(ShapeAnalysis_Wire)& saw,
74 const Handle(ShapeExtend_WireData)& nextsewd,
75 const Standard_Real maxtol,
76 Standard_Real& distmin,
77 Standard_Boolean& revsewd,
78 Standard_Boolean& revnextsewd) const
81 revsewd = revnextsewd = Standard_False;
82 if (nextsewd->NbEdges() == 0) return Standard_True;
84 Handle(ShapeExtend_WireData) sewd = saw->WireData();
85 //add edges into empty WireData
86 if(sewd->NbEdges() == 0) {
91 Standard_Real tailhead, tailtail, headtail, headhead;
92 saw->CheckShapeConnect (tailhead, tailtail, headtail, headhead, nextsewd->Wire(), maxtol);
94 Standard_Real precision = saw->Precision();
96 if ( tailhead > precision && tailtail > precision &&
97 ( saw->LastCheckStatus (ShapeExtend_DONE4) ||
98 saw->LastCheckStatus (ShapeExtend_DONE3) ) ) {
101 revsewd = Standard_True;
102 if (saw->LastCheckStatus (ShapeExtend_DONE3)) {
104 revnextsewd = Standard_True;
108 else if (!saw->LastCheckStatus (ShapeExtend_FAIL) && !saw->LastCheckStatus (ShapeExtend_DONE5)) {
110 revnextsewd = Standard_True;
113 Standard_Boolean OK = !saw->LastCheckStatus (ShapeExtend_FAIL);
114 if (OK) sewd->Add (nextsewd);
118 //=======================================================================
119 //function : ApproxBSplineCurve
121 //=======================================================================
123 void ShapeAlgo_AlgoContainer::ApproxBSplineCurve (const Handle(Geom_BSplineCurve)& bspline,
124 TColGeom_SequenceOfCurve& seq) const
127 Handle(Geom_BSplineCurve) res, modifCurve;
128 TColGeom_SequenceOfCurve SCurve;
130 // si la BSpline est de degre 1 , on approxime .
131 // on passe par le programme des intersections ou tout le travail
132 // est deja fait !!! ( il faut faire des paquets de 30 points
133 // maximum , travailler dans un espace 0,1 pour tenir la precision)
135 if (bspline->Degree() != 1) {
140 // on detecte d`eventuelles cassures par la multiplicite des poles.
141 // Puis on approxime chaque "partie" de BSpline
143 Standard_Integer NbKnots = bspline->NbKnots();
144 Standard_Integer NbPoles = bspline->NbPoles();
145 TColgp_Array1OfPnt Poles(1,NbPoles);
146 TColStd_Array1OfReal Weigs(1,NbPoles); Weigs.Init(1.);
147 TColStd_Array1OfReal Knots(1,NbKnots);
148 TColStd_Array1OfInteger Mults(1,NbKnots);
150 bspline->Poles(Poles);
151 if ( bspline->IsRational()) bspline->Weights(Weigs);
152 bspline->Knots(Knots);
153 bspline->Multiplicities(Mults);
154 Standard_Integer deg = bspline->Degree();
156 Standard_Integer jpole = 1;
157 Standard_Integer j, PoleIndex, I1;
160 for ( Standard_Integer ipole = 1; ipole < NbPoles; ipole++) {
161 if (Poles(ipole).IsEqual(Poles(ipole+1),Precision::Confusion())) {
166 TColgp_Array1OfPnt newPoles(1,jpole);
167 TColStd_Array1OfReal newWeigs(1,jpole); Weigs.Init(1.);
168 Standard_Integer NbNew = jpole - deg + 1;
169 TColStd_Array1OfReal newKnots(1,NbNew);
170 TColStd_Array1OfInteger newMults(1,NbNew);
171 for ( j = 1; j <= NbNew; j++) {
172 newKnots(j) = Knots(I1+j-1);
173 newMults(j) = Mults(I1+j-1);
175 newMults(1) = newMults(NbNew) = deg+1;
176 for ( j = 1; j <= jpole; j++) {
177 newWeigs(j) = Weigs(PoleIndex );
178 newPoles(j) = Poles(PoleIndex++);
181 Handle(Geom_BSplineCurve) newC = new Geom_BSplineCurve
182 (newPoles, newWeigs, newKnots, newMults, deg);
194 Handle(Geom_BSplineCurve) mycurve;
195 Standard_Integer nbcurves = SCurve.Length();
198 SCurve.Append(bspline);
201 for (Standard_Integer itab = 1; itab <= nbcurves; itab++) {
202 mycurve = Handle(Geom_BSplineCurve)::DownCast(SCurve.Value(itab));
203 jpole = mycurve->NbPoles();
205 TColgp_Array1OfPnt newP(1,jpole);
206 mycurve->Poles(newP);
207 Handle(IntSurf_LineOn2S) R = new IntSurf_LineOn2S();
208 Standard_Real u1,v1,u2,v2;
211 for( j=1; j<=jpole; j++) {
212 IntSurf_PntOn2S POn2S;
213 POn2S.SetValue(newP(j),u1,v1,u2,v2);
216 GeomInt_WLApprox theapp3d;
217 Standard_Real Tol = Precision::Approximation();
218 theapp3d.SetParameters(Tol, Tol, 4, 8, 0, Standard_True);
219 Handle(IntPatch_WLine) WL = new IntPatch_WLine(R, Standard_False);
220 Standard_Integer indicemin = 1;
221 Standard_Integer indicemax = jpole;
222 theapp3d.Perform(WL, Standard_True, Standard_False,
223 Standard_False, indicemin, indicemax);
224 if (!theapp3d.IsDone()) {
225 modifCurve = mycurve;
227 else if (theapp3d.NbMultiCurves() != 1) {
228 modifCurve = mycurve;
231 const AppParCurves_MultiBSpCurve& mbspc = theapp3d.Value(1);
232 Standard_Integer nbpoles = mbspc.NbPoles();
233 TColgp_Array1OfPnt tpoles(1,nbpoles);
234 mbspc.Curve(1,tpoles);
235 modifCurve = new Geom_BSplineCurve(tpoles,
237 mbspc.Multiplicities(),
242 modifCurve = mycurve;
244 seq.Append(modifCurve);
248 //=======================================================================
249 //function : ApproxBSplineCurve
251 //=======================================================================
253 void ShapeAlgo_AlgoContainer::ApproxBSplineCurve (const Handle(Geom2d_BSplineCurve)& bspline,
254 TColGeom2d_SequenceOfCurve& seq) const
257 Handle(Geom2d_BSplineCurve) res, modifCurve;
258 TColGeom2d_SequenceOfCurve SCurve;
260 // si la BSpline est de degre 1 , on approxime .
261 // on passe par le programme des intersections ou tout le travail
262 // est deja fait !!! ( il faut faire des paquets de 30 points
263 // maximum , travailler dans un espace 0,1 pour tenir la precision
264 // puis reconstruire une BSpline somme des toutes les Bspline).
266 if (bspline->Degree() != 1) {
271 // on detecte d`eventuelles cassures par la multiplicite des poles.
272 // Puis on approxime chaque "partie" de BSpline et on reconstruit
273 // une BSpline = somme des BSplines traitees
275 Standard_Integer NbKnots = bspline->NbKnots();
276 Standard_Integer NbPoles = bspline->NbPoles();
277 TColgp_Array1OfPnt2d Poles(1,NbPoles);
278 TColStd_Array1OfReal Weigs(1,NbPoles); Weigs.Init(1.);
279 TColStd_Array1OfReal Knots(1,NbKnots);
280 TColStd_Array1OfInteger Mults(1,NbKnots);
282 bspline->Poles(Poles);
283 if ( bspline->IsRational()) bspline->Weights(Weigs);
284 bspline->Knots(Knots);
285 bspline->Multiplicities(Mults);
286 Standard_Integer deg = bspline->Degree();
288 Standard_Integer jpole = 1;
289 Standard_Integer j, PoleIndex, I1;
292 for ( Standard_Integer ipole = 1; ipole < NbPoles; ipole++) {
293 if (Poles(ipole).IsEqual(Poles(ipole+1),Precision::PConfusion())) {
298 TColgp_Array1OfPnt2d newPoles(1,jpole);
299 TColStd_Array1OfReal newWeigs(1,jpole); Weigs.Init(1.);
300 Standard_Integer NbNew = jpole - deg + 1;
301 TColStd_Array1OfReal newKnots(1,NbNew);
302 TColStd_Array1OfInteger newMults(1,NbNew);
303 for ( j = 1; j <= NbNew; j++) {
304 newKnots(j) = Knots(I1+j-1);
305 newMults(j) = Mults(I1+j-1);
307 newMults(1) = newMults(NbNew) = deg+1;
308 for ( j = 1; j <= jpole; j++) {
309 newWeigs(j) = Weigs(PoleIndex );
310 newPoles(j) = Poles(PoleIndex++);
313 Handle(Geom2d_BSplineCurve) newC = new Geom2d_BSplineCurve
314 (newPoles, newWeigs, newKnots, newMults, deg);
326 Handle(Geom2d_BSplineCurve) mycurve;
327 Standard_Integer nbcurves = SCurve.Length();
330 SCurve.Append(bspline);
333 for (Standard_Integer itab = 1; itab <= nbcurves; itab++) {
334 mycurve = Handle(Geom2d_BSplineCurve)::DownCast(SCurve.Value(itab));
335 jpole = mycurve->NbPoles();
337 TColgp_Array1OfPnt P(1,jpole);
338 TColgp_Array1OfPnt2d newP(1,jpole);
339 mycurve->Poles(newP);
340 Handle(IntSurf_LineOn2S) R = new IntSurf_LineOn2S();
343 for( j=1; j<=jpole; j++) {
344 IntSurf_PntOn2S POn2S;
345 POn2S.SetValue(P(j),newP(j).X(),newP(j).Y(),u2,v2);
348 GeomInt_WLApprox theapp3d;
349 Standard_Real Tol = Precision::PApproximation();
350 theapp3d.SetParameters(Tol, Tol, 4, 8, 0, Standard_True);
351 Handle(IntPatch_WLine) WL = new IntPatch_WLine(R, Standard_False);
352 Standard_Integer indicemin = 1;
353 Standard_Integer indicemax = jpole;
354 theapp3d.Perform(WL, Standard_False, Standard_True,
355 Standard_False, indicemin, indicemax);
356 if (!theapp3d.IsDone()) {
357 modifCurve = mycurve;
359 else if (theapp3d.NbMultiCurves() != 1) {
360 modifCurve = mycurve;
363 const AppParCurves_MultiBSpCurve& mbspc = theapp3d.Value(1);
364 Standard_Integer nbpoles = mbspc.NbPoles();
365 TColgp_Array1OfPnt2d tpoles(1,nbpoles);
366 mbspc.Curve(1,tpoles);
367 for( j=1; j<=jpole; j++) {
369 modifCurve = new Geom2d_BSplineCurve(tpoles,
371 mbspc.Multiplicities(),
376 modifCurve = mycurve;
378 seq.Append(modifCurve);
382 //=======================================================================
383 //function : C0ShapeToC1Shape
385 //=======================================================================
387 TopoDS_Shape ShapeAlgo_AlgoContainer::C0ShapeToC1Shape (const TopoDS_Shape& shape,
388 const Standard_Real tol) const
390 ShapeUpgrade_ShapeDivideContinuity sdc(shape);
391 sdc.SetTolerance(tol);
392 sdc.SetBoundaryCriterion(GeomAbs_C1);
393 sdc.SetSurfaceCriterion(GeomAbs_C1);
398 //=======================================================================
399 //function : ConvertSurfaceToBSpline
401 //=======================================================================
403 Handle(Geom_BSplineSurface) ShapeAlgo_AlgoContainer::ConvertSurfaceToBSpline(const Handle(Geom_Surface)& surf,
404 const Standard_Real UF,
405 const Standard_Real UL,
406 const Standard_Real VF,
407 const Standard_Real VL) const
409 return ShapeConstruct::ConvertSurfaceToBSpline(surf, UF, UL, VF, VL,
410 Precision::Confusion(), GeomAbs_C1, 100,
411 Geom_BSplineSurface::MaxDegree());
414 //=======================================================================
415 //function : HomoWires
417 //=======================================================================
419 Standard_Boolean ShapeAlgo_AlgoContainer::HomoWires(const TopoDS_Wire& wireIn1,
420 const TopoDS_Wire& wireIn2,
421 TopoDS_Wire& wireOut1,
422 TopoDS_Wire& wireOut2,
423 const Standard_Boolean) const
425 //Standard_Boolean res = Standard_False; //szv#4:S4163:12Mar99 not needed
426 TopoDS_Iterator Cook, Perry;
427 TopoDS_Edge edge1, edge2;
428 TopLoc_Location loc1, loc2;
429 // BRepBuilderAPI_MakeWire makeWire1, makeWire2;
430 ShapeExtend_WireData makeWire1, makeWire2;
431 Standard_Boolean iterCook, iterPerry;
432 Standard_Integer nEdges1, nEdges2;
433 Standard_Real length1, length2;
434 Standard_Real first1, first2;
435 Standard_Real last1, last2;
436 Standard_Real delta1, delta2;
438 Handle (Geom_Curve) crv1;
439 Handle (Geom_Curve) crv2;
441 //Standard_Boolean notEnd = Standard_True; //szv#4:S4163:12Mar99 unused
442 Standard_Integer nbCreatedEdges = 0;
444 //TopoDS_Vertex v11,v12,v21,v22
445 Handle(ShapeFix_Wire) sfw = new ShapeFix_Wire();
448 TopoDS_Wire wireIn11 = sfw->Wire() ;
451 TopoDS_Wire wireIn22 = sfw->Wire() ;
453 iterCook = iterPerry = Standard_True;
454 length1 = length2 = 0.;
455 nEdges1 = nEdges2 = 0;
456 for (Cook.Initialize(wireIn11); Cook.More(); Cook.Next()) {
458 edge1 = TopoDS::Edge(Cook.Value());
459 crv1 = BRep_Tool::Curve(edge1, loc1, first1, last1);
460 length1 += last1 - first1;
462 for (Perry.Initialize(wireIn22); Perry.More(); Perry.Next()) {
464 edge2 = TopoDS::Edge(Perry.Value());
465 crv2 = BRep_Tool::Curve(edge2, loc2, first2, last2);
466 length2 += last2 - first2;
468 Standard_Real epsilon = Precision::PConfusion() * (length1 + length2);
469 if (nEdges1 == 1 && nEdges2 == 1){
472 return Standard_True; //szv#4:S4163:12Mar99 `res=` not needed
475 if (length1 < epsilon) {
476 Cook.Initialize(wireIn11);
477 for (Perry.Initialize(wireIn22); Perry.More(); Perry.Next()) {
478 edge1 = TopoDS::Edge(Cook.Value());
479 makeWire1.Add(edge1);
481 wireOut1 = makeWire1.Wire();
483 return Standard_True; //szv#4:S4163:12Mar99 `res=` not needed
485 if (length2 < epsilon) {
486 Perry.Initialize(wireIn22);
487 for (Cook.Initialize(wireIn11); Cook.More(); Cook.Next()) {
488 edge2 = TopoDS::Edge(Perry.Value());
489 makeWire2.Add(edge2);
492 wireOut2 = makeWire2.Wire();
493 return Standard_True; //szv#4:S4163:12Mar99 `res=` not needed
497 Standard_Real ratio = length2 / length1;
499 Cook.Initialize(wireIn11);
500 Perry.Initialize(wireIn22);
501 edge1 = TopoDS::Edge(Cook.Value());
502 edge2 = TopoDS::Edge(Perry.Value());
503 // essai mjm du 22/05/97
504 Standard_Boolean IsToReverse1 = Standard_False;
505 Standard_Boolean IsToReverse2 = Standard_False;
506 if (edge1.Orientation() == TopAbs_REVERSED)
507 IsToReverse1 = Standard_True;
508 if (edge2.Orientation() == TopAbs_REVERSED)
509 IsToReverse2 = Standard_True;
510 crv1 = BRep_Tool::Curve(edge1, loc1, first1, last1);
511 crv2 = BRep_Tool::Curve(edge2, loc2, first2, last2);
512 delta1 = last1 - first1;
513 delta2 = last2 - first2;
514 while (nbCreatedEdges < (nEdges1 + nEdges2-1)) { /*just a security. */
516 if ((delta1*ratio - delta2) > epsilon) {
517 BRepBuilderAPI_MakeEdge makeEdge1;
519 makeEdge1.Init(crv1, first1, first1 + delta2/ratio);
520 first1+= delta2/ratio;
522 else { // gka BUC60685
523 makeEdge1.Init(crv1, last1 - delta2/ratio , last1);
524 last1 -= delta2/ratio;
526 BRepBuilderAPI_MakeEdge makeEdge2(crv2, first2, last2);
527 edge1 = makeEdge1.Edge();
528 edge2 = makeEdge2.Edge();
529 // essai mjm du 22/05/97
530 iterCook = Standard_False;
531 //first1 += delta2/ratio;
532 delta1 = last1 - first1;
533 iterPerry = Standard_True;
536 else if (Abs(delta1*ratio - delta2) <= epsilon) {
537 BRepBuilderAPI_MakeEdge makeEdge1(crv1, first1, last1);
538 BRepBuilderAPI_MakeEdge makeEdge2(crv2, first2, last2);
539 edge1 = makeEdge1.Edge();
540 edge2 = makeEdge2.Edge();
541 iterCook = Standard_True;
542 iterPerry = Standard_True;
545 else /*((delta1*ratio - delta2) < -epsilon)*/ {
546 BRepBuilderAPI_MakeEdge makeEdge1(crv1, first1, last1);
547 edge1 = makeEdge1.Edge();
548 BRepBuilderAPI_MakeEdge makeEdge2;
550 makeEdge2.Init(crv2, first2, first2 + delta1*ratio);
551 first2 += delta1*ratio;
553 else { // gka BUC60685
554 makeEdge2.Init(crv2, last2 - delta1*ratio, last2);
555 last2 -= delta1*ratio;
557 edge1 = makeEdge1.Edge();
558 edge2 = makeEdge2.Edge();
559 iterCook = Standard_True;
560 iterPerry = Standard_False;
561 //first2 += delta1*ratio;
562 delta2 = last2 - first2;
567 if ( IsToReverse1) edge1.Reverse();
568 if ( IsToReverse2) edge2.Reverse();
569 makeWire1.Add(edge1);
570 makeWire2.Add(edge2);
572 if (iterCook && iterPerry) {
573 TopoDS_Iterator Copernic = Cook;
576 if (!Copernic.More()) {
577 wireOut1 = makeWire1.Wire();
578 wireOut2 = makeWire2.Wire();
579 return Standard_True; //szv#4:S4163:12Mar99 `res=` not needed
584 edge1 = TopoDS::Edge(Cook.Value());
585 if (edge1.Orientation() == TopAbs_REVERSED)
586 IsToReverse1 = Standard_True;
587 else IsToReverse1 = Standard_False;
588 crv1 = BRep_Tool::Curve(edge1, loc1, first1, last1);
589 delta1 = last1 - first1;
593 edge2 = TopoDS::Edge(Perry.Value());
594 if (edge2.Orientation() == TopAbs_REVERSED)
595 IsToReverse2 = Standard_True;
596 else IsToReverse2 = Standard_False;
597 crv2 = BRep_Tool::Curve(edge2, loc2, first2, last2);
598 delta2 = last2 - first2;
602 return Standard_False; //szv#4:S4163:12Mar99 `res=` not needed
605 //=======================================================================
606 //function : C0BSplineToSequenceOfC1BSplineCurve
608 //=======================================================================
610 Standard_Boolean ShapeAlgo_AlgoContainer::C0BSplineToSequenceOfC1BSplineCurve(const Handle(Geom_BSplineCurve)& BS,
611 Handle(TColGeom_HSequenceOfBoundedCurve)& seqBS) const
613 return ShapeUpgrade::C0BSplineToSequenceOfC1BSplineCurve (BS, seqBS);
616 //=======================================================================
617 //function : C0BSplineToSequenceOfC1BSplineCurve
619 //=======================================================================
621 Standard_Boolean ShapeAlgo_AlgoContainer::C0BSplineToSequenceOfC1BSplineCurve(const Handle(Geom2d_BSplineCurve)& BS,
622 Handle(TColGeom2d_HSequenceOfBoundedCurve)& seqBS) const
624 return ShapeUpgrade::C0BSplineToSequenceOfC1BSplineCurve (BS, seqBS);
627 //=======================================================================
628 //function : OuterWire
630 //=======================================================================
632 TopoDS_Wire ShapeAlgo_AlgoContainer::OuterWire(const TopoDS_Face& face) const
634 return ShapeAnalysis::OuterWire(face);
637 //=======================================================================
638 //function : ConvertToPeriodic
640 //=======================================================================
642 Handle(Geom_Surface) ShapeAlgo_AlgoContainer::ConvertToPeriodic (const Handle(Geom_Surface)& surf) const
644 ShapeCustom_Surface scs (surf);
645 return scs.ConvertToPeriodic (Standard_False);
648 //=======================================================================
649 //function : GetFaceUVBounds
651 //=======================================================================
653 void ShapeAlgo_AlgoContainer::GetFaceUVBounds (const TopoDS_Face& F,
657 Standard_Real& Vmax) const
659 ShapeAnalysis::GetFaceUVBounds (F, Umin, Umax, Vmin, Vmax);
662 //=======================================================================
663 //function : ConvertCurveToBSpline
665 //=======================================================================
667 Handle(Geom_BSplineCurve) ShapeAlgo_AlgoContainer::ConvertCurveToBSpline(const Handle(Geom_Curve)& C3D,
668 const Standard_Real First,
669 const Standard_Real Last,
670 const Standard_Real Tol3d,
671 const GeomAbs_Shape Continuity,
672 const Standard_Integer MaxSegments,
673 const Standard_Integer MaxDegree) const
675 return ShapeConstruct::ConvertCurveToBSpline(C3D, First, Last, Tol3d, Continuity, MaxSegments, MaxDegree);