1 // Created on: 1998-01-14
2 // Created by: Philippe MANGIN
3 // Copyright (c) 1998-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
6 // This file is part of Open CASCADE Technology software library.
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.
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
18 #include <BRepFill_LocationLaw.ixx>
20 #include <BRepTools_WireExplorer.hxx>
21 #include <BRep_Tool.hxx>
22 #include <BRep_Builder.hxx>
23 #include <BRepAdaptor_Curve.hxx>
24 #include <Adaptor3d_HCurve.hxx>
26 #include <TopoDS_Edge.hxx>
28 #include <TopLoc_Location.hxx>
30 #include <GeomFill_LocationLaw.hxx>
34 #include <gp_Trsf.hxx>
35 #include <GCPnts_AbscissaPoint.hxx>
36 #include <TColgp_Array1OfPnt2d.hxx>
37 #include <TColgp_Array1OfVec2d.hxx>
38 #include <TColStd_SequenceOfInteger.hxx>
39 #include <Precision.hxx>
40 #include <BRepBuilderAPI_Transform.hxx>
43 //=======================================================================
45 //purpose : Norm of a Matrix
46 //=======================================================================
48 static Standard_Real Norm(const gp_Mat& M) {
49 Standard_Real R, Norme;
52 Norme = Abs(Coord.X()) + Abs(Coord.Y())+ Abs(Coord.Z());
54 R = Abs(Coord.X()) + Abs(Coord.Y())+ Abs(Coord.Z());
55 if (R>Norme) Norme = R;
57 R = Abs(Coord.X()) + Abs(Coord.Y())+ Abs(Coord.Z());
58 if (R>Norme) Norme = R;
63 //=======================================================================
65 //purpose : Calculate tranformation T such as T.M2 = M1
66 //=======================================================================
68 static void ToG0(const gp_Mat& M1, const gp_Mat& M2, gp_Mat& T) {
73 //=======================================================================
74 //function : BRepFill_LocationLaw
76 //=======================================================================
78 void BRepFill_LocationLaw::Init(const TopoDS_Wire& Path)
81 Standard_Integer NbEdge;
82 BRepTools_WireExplorer wexp;
83 // Class BRep_Tool without fields and without Constructor :
90 for (NbEdge=0, wexp.Init(myPath);
91 wexp.More(); wexp.Next())
92 // if (! B.Degenerated(wexp.Current())) NbEdge++;
93 if (! BRep_Tool::Degenerated(wexp.Current())) NbEdge++;
96 myLaws = new (GeomFill_HArray1OfLocationLaw)(1, NbEdge);
97 myLength = new (TColStd_HArray1OfReal) (1, NbEdge+1);
99 myLength->SetValue(1, 0.);
100 myEdges = new (TopTools_HArray1OfShape) (1, NbEdge);
105 //=======================================================================
106 //function : GetStatus
108 //=======================================================================
109 GeomFill_PipeError BRepFill_LocationLaw::GetStatus() const
111 Standard_Integer ii, N = myLaws->Length();
112 GeomFill_PipeError Status = GeomFill_PipeOk;
113 for (ii=1; ii<=N && (Status == GeomFill_PipeOk); ii++) {
114 Status = myLaws->Value(ii)->ErrorStatus();
119 //=======================================================================
120 //function : TangentIsMain
122 //=======================================================================
123 void BRepFill_LocationLaw::TangentIsMain()
128 //=======================================================================
129 //function : NormalIsMain
131 //=======================================================================
132 void BRepFill_LocationLaw::NormalIsMain()
137 //=======================================================================
138 //function : BiNormalIsMain
140 //=======================================================================
141 void BRepFill_LocationLaw::BiNormalIsMain()
146 //=======================================================================
147 //function : TransformInCompatibleLaw
148 //purpose : Set in continuity of laws
149 //=======================================================================
150 void BRepFill_LocationLaw::TransformInCompatibleLaw(const Standard_Real TolAngular)
153 Standard_Real First, Last, Angle;
154 Standard_Integer ipath;
156 gp_Vec V, T1, T2, N1, N2;
159 myLaws->Value(1)->GetDomain(First, Last);
161 for (ipath=2; ipath<=myLaws->Length(); ipath++) {
162 myLaws->Value(ipath-1)->D0(Last, M1, V);
163 myLaws->Value(ipath)->GetDomain(First, Last);
164 myLaws->Value(ipath)->D0(First, M2, V);
165 T1.SetXYZ(M1.Column(3));
166 T2.SetXYZ(M2.Column(3));
167 N1.SetXYZ(M1.Column(1));
168 N2.SetXYZ(M2.Column(1));
169 if (T1.IsParallel(T2, TolAngular ) &&
170 !T1.IsOpposite(T2, TolAngular)) { // Correction G0
177 alpha = T2.AngleWithRef(T1, cross);
178 gp_Ax1 axe(gp::Origin(), cross.XYZ());
179 N2.Rotate(axe, alpha);
182 if (N2.Dot(T1) > 1.e-9) {
183 cout << "Inprecision in TransformInCompatibleLaw" << endl;
184 cout << "--- T1.R(N2) = " << N2.Dot(T1) << endl;
187 tt.Rotate(axe, alpha);
188 cout << "--- T1.R(T2) = " << tt.Dot(T1) << endl;
189 cout << "--- R(N2).R(T2) = " << N2.Dot(tt) << endl;
192 Angle = N2.AngleWithRef(N1, T1);
193 Trsf.SetRotation(OZ, Angle);
195 myLaws->Value(ipath)->SetTrsf(Trsf);
199 //=======================================================================
200 //function : TransformInG0Law
201 //purpose : Set in continuity of laws
202 //=======================================================================
203 void BRepFill_LocationLaw::TransformInG0Law()
206 Standard_Real First, Last;
207 Standard_Integer ipath;
208 gp_Mat M1, M2, aux;//,Trsf
210 myLaws->Value(1)->GetDomain(First, Last);
211 for (ipath=2; ipath<=myLaws->Length(); ipath++) {
212 myLaws->Value(ipath-1)->D0(Last, M1, V);
213 myLaws->Value(ipath)->GetDomain(First, Last);
214 myLaws->Value(ipath)->D0(First, M2, V);
216 myLaws->Value(ipath)->SetTrsf(aux);
219 // Is the law periodical ?
220 if (myPath.Closed()) {
221 myLaws->Value(myLaws->Length())->D0(Last, M1, V);
222 myLaws->Value(1)->GetDomain(First, Last);
223 myLaws->Value(1)->D0(First, M2, V);
227 //=======================================================================
228 //function : DeleteTransform
229 //purpose : Remove the setting in continuity of law.
230 //=======================================================================
231 void BRepFill_LocationLaw::DeleteTransform()
235 for (Standard_Integer ii=1; ii<=myEdges->Length(); ii++) {
236 myLaws->ChangeValue(ii)->SetTrsf(Id);
241 //=======================================================================
243 //purpose : Find "Holes"
244 //=======================================================================
245 Standard_Integer BRepFill_LocationLaw::NbHoles(const Standard_Real Tol)
247 if (myDisc.IsNull()) {
248 TColStd_SequenceOfInteger Seq;
249 Standard_Integer ii, NbDisc;
250 for (ii=2, NbDisc=-1; ii<=myLaws->Length()+1; ii++) {
251 if (IsG1(ii-1, Tol, 1.e-12) == -1) {
255 NbDisc = Seq.Length();
257 myDisc = new (TColStd_HArray1OfInteger)(1, NbDisc);
258 for (ii=1; ii<=NbDisc; ii++)
259 myDisc->SetValue(ii, Seq(ii));
262 if (myDisc.IsNull()) return 0;
263 return myDisc->Length();
267 //=======================================================================
270 //=======================================================================
271 void BRepFill_LocationLaw::Holes(TColStd_Array1OfInteger& Disc) const
273 if (!myDisc.IsNull()) {
274 for (Standard_Integer ii=1; ii<=myDisc->Length(); ii++)
275 Disc(ii) = myDisc->Value(ii);
279 //=======================================================================
282 //=======================================================================
283 Standard_Integer BRepFill_LocationLaw::NbLaw() const
285 return myLaws->Length();
288 //=======================================================================
291 //=======================================================================
292 const Handle(GeomFill_LocationLaw)&
293 BRepFill_LocationLaw::Law(const Standard_Integer Index) const
295 return myLaws->Value(Index);
298 //=======================================================================
301 //=======================================================================
302 const TopoDS_Wire& BRepFill_LocationLaw::Wire() const
307 //=======================================================================
310 //=======================================================================
311 const TopoDS_Edge& BRepFill_LocationLaw::Edge(const Standard_Integer Index) const
313 return TopoDS::Edge(myEdges->Value(Index));
316 //=======================================================================
319 //=======================================================================
320 TopoDS_Vertex BRepFill_LocationLaw::Vertex(const Standard_Integer Index) const
324 if (Index <= myEdges->Length()) {
325 E = TopoDS::Edge(myEdges->Value(Index));
326 if (E.Orientation() == TopAbs_REVERSED)
327 V = TopExp::LastVertex(E);
328 else V = TopExp::FirstVertex(E);
330 else if (Index == myEdges->Length()+1) {
331 E = TopoDS::Edge(myEdges->Value(Index-1));
332 if (E.Orientation() == TopAbs_REVERSED)
333 V = TopExp::FirstVertex(E);
334 else V = TopExp::LastVertex(E);
339 //===================================================================
340 //function : PerformVertex
341 //purpose : Calculate a vertex of sweeping from a vertex of section
342 // and the index of the edge in the trajectory
343 //===================================================================
344 void BRepFill_LocationLaw::PerformVertex(const Standard_Integer Index,
345 const TopoDS_Vertex& Input,
346 const Standard_Real TolMin,
347 TopoDS_Vertex& Output,
348 const Standard_Integer ILoc) const
351 Standard_Boolean IsBary = (ILoc == 0);
352 Standard_Real First, Last;
357 if (Index>0 && Index<myLaws->Length()) {
359 myLaws->Value(Index)->GetDomain(First, Last);
360 myLaws->Value(Index)->D0(Last, M1, V1);
364 myLaws->Value(Index+1)->GetDomain(First, Last);
366 myLaws->Value(Index+1)->D0(First, M2, V2);
368 myLaws->Value(Index+1)->D0(First, M1, V1);
372 if (Index == 0 || Index == myLaws->Length()) {
373 if (!myPath.Closed() || (IsG1(Index, TolMin) != 1)) {
374 IsBary = Standard_False;
376 myLaws->Value(1)->GetDomain(First, Last);
377 myLaws->Value(1)->D0(First, M1, V1);
380 myLaws->Value(myLaws->Length())->GetDomain(First, Last);
381 myLaws->Value(myLaws->Length())->D0(Last, M1, V1);
386 myLaws->Value(myLaws->Length())->GetDomain(First, Last);
387 myLaws->Value(myLaws->Length())->D0(Last, M1, V1);
391 myLaws->Value(1)->GetDomain(First, Last);
393 myLaws->Value(1)->D0(First, M2, V2);
395 myLaws->Value(1)->D0(First, M1, V1);
400 P = BRep_Tool::Pnt(Input);
403 gp_XYZ P1(P.XYZ()), P2(P.XYZ());
409 P.ChangeCoord().SetLinearForm(0.5, P1, 0.5, P2);
411 Standard_Real Tol = P1.Modulus()/2;
413 B.MakeVertex(Output, P, Tol);
416 P.ChangeCoord() *= M1;
417 P.ChangeCoord() += V1.XYZ();
418 B.MakeVertex(Output, P, TolMin);
423 //=======================================================================
424 //function : CurvilinearBounds
426 //=======================================================================
427 void BRepFill_LocationLaw::CurvilinearBounds(const Standard_Integer Index,
428 Standard_Real& First,
429 Standard_Real& Last) const
431 First = myLength->Value(Index);
432 Last = myLength->Value(Index+1);
433 if (Last<0) { //It is required to carry out the calculation
434 Standard_Integer ii, NbE = myEdges->Length();
435 Standard_Real Length, f, l;
436 GCPnts_AbscissaPoint AbsC;
438 for (ii=1, Length=0.; ii<=NbE; ii++) {
439 myLaws->Value(ii)->GetDomain(f, l);
440 Length += AbsC.Length(myLaws->Value(ii)->GetCurve()->GetCurve(), myTol);
441 myLength->SetValue(ii+1, Length);
444 First = myLength->Value(Index);
445 Last = myLength->Value(Index+1);
449 Standard_Boolean BRepFill_LocationLaw::IsClosed() const
451 return myPath.Closed();
454 //=======================================================================
456 //purpose : Evaluate the continuity of the law by a vertex
457 //=======================================================================
459 BRepFill_LocationLaw::IsG1(const Standard_Integer Index,
460 const Standard_Real SpatialTolerance,
461 const Standard_Real AngularTolerance) const
463 gp_Vec V1, DV1, V2, DV2;
464 gp_Mat M1, M2, DM1, DM2;
465 Standard_Real First, Last, EpsNul = 1.e-12;
466 Standard_Real TolEps = SpatialTolerance;
467 Standard_Boolean Ok_D1 = Standard_False;
470 TColgp_Array1OfPnt2d Bid1 (1,1);
471 TColgp_Array1OfVec2d Bid2 (1,1);
473 if (Index>0 && Index<myLaws->Length()) {
474 myLaws->Value(Index)->GetDomain(First, Last);
475 Ok_D1 = myLaws->Value(Index)->D1(Last, M1, V1, DM1, DV1,
477 if (!Ok_D1) myLaws->Value(Index)->D0(Last, M1, V1);
479 myLaws->Value(Index+1)->GetDomain(First, Last);
481 Ok_D1 = myLaws->Value(Index+1)->D1(First, M2, V2, DM2, DV2,
483 if (!Ok_D1) myLaws->Value(Index+1)->D0(First, M2, V2);
485 E = TopoDS::Edge(myEdges->Value(Index+1));
487 if (Index == 0 || Index == myLaws->Length()) {
488 if (!myPath.Closed()) return -1;
489 myLaws->Value(myLaws->Length())->GetDomain(First, Last);
490 Ok_D1 = myLaws->Value(myLaws->Length())->D1(Last, M1, V1, DM1, DV1,
492 if (!Ok_D1) myLaws->Value(myLaws->Length())->D0(Last, M1, V1);
494 myLaws->Value(1)->GetDomain(First, Last);
496 myLaws->Value(1)->D1(First, M2, V2, DM2, DV2,
498 if (!Ok_D1) myLaws->Value(1)->D0(First, M2, V2);
500 E = TopoDS::Edge(myEdges->Value(1));
503 if (E.Orientation() == TopAbs_REVERSED)
504 V = TopExp::LastVertex(E);
506 V = TopExp::FirstVertex(E);
508 TolEps += 2*BRep_Tool::Tolerance(V);
510 Standard_Boolean isG0 = Standard_True;
511 Standard_Boolean isG1 = Standard_True;
513 if ((V1-V2).Magnitude() > TolEps) isG0 = Standard_False;
514 if (Norm(M1-M2) > SpatialTolerance) isG0 = Standard_False;
516 if (!isG0) return -1;
517 if (!Ok_D1) return 0; // No control of the derivative
519 if ( (DV1.Magnitude()>EpsNul) && (DV2.Magnitude()>EpsNul)
520 && (DV1.Angle(DV2) > AngularTolerance) ) isG1 = Standard_False;
522 // For the next, the tests are mostly empirical
523 Standard_Real Norm1 = Norm(DM1);
524 Standard_Real Norm2 = Norm(DM2);
525 // It two 2 norms are null, it is good
526 if ((Norm1 > EpsNul) || (Norm2 > EpsNul)) {
527 // otherwise the normalized matrices are compared
528 if ((Norm1 > EpsNul) && (Norm2 > EpsNul)) {
531 if (Norm(DM1 - DM2) > AngularTolerance) isG1 = Standard_False;
533 else isG1 = Standard_False; // 1 Null the other is not
541 //=======================================================================
542 //function : Parameter
544 //=======================================================================
545 void BRepFill_LocationLaw::Parameter(const Standard_Real Abcissa,
546 Standard_Integer& Index,
549 Standard_Integer iedge, NbE=myEdges->Length();
550 Standard_Boolean Trouve = Standard_False;
552 //Control that the lengths are calculated
553 if (myLength->Value(NbE+1) < 0) {
555 CurvilinearBounds(NbE, f, l);
559 for (iedge=1; iedge<=NbE && !Trouve; ) {
560 if (myLength->Value(iedge+1) >= Abcissa) {
561 Trouve = Standard_True;
568 const Handle(GeomFill_LocationLaw)& Law = myLaws->Value(iedge);
569 Law->GetDomain(f, l);
571 if (Abcissa == myLength->Value(iedge+1)) {
574 else if (Abcissa == myLength->Value(iedge)) {
580 myLaws->Value(iedge)->GetCurve()->GetCurve(),
581 Abcissa-myLength->Value(iedge), f);
582 U = AbsC.Parameter();
592 //===================================================================
594 //purpose : Position of a section, with a given curviline abscissa
595 //===================================================================
596 void BRepFill_LocationLaw::D0(const Standard_Real Abcissa,
600 Standard_Integer ind;
604 Parameter(Abcissa, ind, u);
607 myLaws->Value(ind)->D0(u, M, V);
609 fila.SetValues(M(1,1), M(1,2), M(1,3), V.X(),
610 M(2,1), M(2,2), M(2,3), V.Y(),
611 M(3,1), M(3,2), M(3,3), V.Z(),
613 //TopLoc_Location Loc(fila);
614 //W.Location(Loc.Multiplied(W.Location()));
615 W = BRepBuilderAPI_Transform(W, fila, Standard_True); //copy
616 ///////////////////////////////////////////
621 cout << "BRepFill_LocationLaw::D0 : Attention position out of limits"
627 //=======================================================================
628 //function : Abscissa
629 //purpose : Calculate the abscissa of a point
630 //=======================================================================
631 Standard_Real BRepFill_LocationLaw::Abscissa(const Standard_Integer Index,
632 const Standard_Real Param)
634 GCPnts_AbscissaPoint AbsC;
635 Standard_Real Length = myLength->Value(Index);
638 CurvilinearBounds(Index, bid, Length);
641 Length += AbsC.Length(myLaws->Value(Index)->GetCurve()->GetCurve(),
642 myLaws->Value(Index)->GetCurve()->FirstParameter(),