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 under
9 // the terms of the GNU Lesser General Public License 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 <Adaptor3d_HCurve.hxx>
19 #include <BRep_Builder.hxx>
20 #include <BRep_Tool.hxx>
21 #include <BRepAdaptor_Curve.hxx>
22 #include <BRepBuilderAPI_Transform.hxx>
23 #include <BRepFill_LocationLaw.hxx>
24 #include <BRepTools_WireExplorer.hxx>
25 #include <GCPnts_AbscissaPoint.hxx>
26 #include <GeomFill_LocationLaw.hxx>
28 #include <gp_Trsf.hxx>
31 #include <Precision.hxx>
32 #include <Standard_OutOfRange.hxx>
33 #include <Standard_Type.hxx>
34 #include <TColgp_Array1OfPnt2d.hxx>
35 #include <TColgp_Array1OfVec2d.hxx>
36 #include <TColStd_SequenceOfInteger.hxx>
38 #include <TopLoc_Location.hxx>
40 #include <TopoDS_Edge.hxx>
41 #include <TopoDS_Shape.hxx>
42 #include <TopoDS_Vertex.hxx>
43 #include <TopoDS_Wire.hxx>
45 //=======================================================================
47 //purpose : Norm of a Matrix
48 //=======================================================================
49 static Standard_Real Norm(const gp_Mat& M) {
50 Standard_Real R, Norme;
53 Norme = Abs(Coord.X()) + Abs(Coord.Y())+ Abs(Coord.Z());
55 R = Abs(Coord.X()) + Abs(Coord.Y())+ Abs(Coord.Z());
56 if (R>Norme) Norme = R;
58 R = Abs(Coord.X()) + Abs(Coord.Y())+ Abs(Coord.Z());
59 if (R>Norme) Norme = R;
64 //=======================================================================
66 //purpose : Calculate tranformation T such as T.M2 = M1
67 //=======================================================================
69 static void ToG0(const gp_Mat& M1, const gp_Mat& M2, gp_Mat& T) {
74 //=======================================================================
75 //function : BRepFill_LocationLaw
77 //=======================================================================
79 void BRepFill_LocationLaw::Init(const TopoDS_Wire& Path)
82 Standard_Integer NbEdge;
83 BRepTools_WireExplorer wexp;
84 // Class BRep_Tool without fields and without Constructor :
91 for (NbEdge=0, wexp.Init(myPath);
92 wexp.More(); wexp.Next())
93 // if (! B.Degenerated(wexp.Current())) NbEdge++;
94 if (! BRep_Tool::Degenerated(wexp.Current())) NbEdge++;
97 myLaws = new (GeomFill_HArray1OfLocationLaw)(1, NbEdge);
98 myLength = new (TColStd_HArray1OfReal) (1, NbEdge+1);
100 myLength->SetValue(1, 0.);
101 myEdges = new (TopTools_HArray1OfShape) (1, NbEdge);
106 //=======================================================================
107 //function : GetStatus
109 //=======================================================================
110 GeomFill_PipeError BRepFill_LocationLaw::GetStatus() const
112 Standard_Integer ii, N = myLaws->Length();
113 GeomFill_PipeError Status = GeomFill_PipeOk;
114 for (ii=1; ii<=N && (Status == GeomFill_PipeOk); ii++) {
115 Status = myLaws->Value(ii)->ErrorStatus();
120 //=======================================================================
121 //function : TangentIsMain
123 //=======================================================================
124 void BRepFill_LocationLaw::TangentIsMain()
129 //=======================================================================
130 //function : NormalIsMain
132 //=======================================================================
133 void BRepFill_LocationLaw::NormalIsMain()
138 //=======================================================================
139 //function : BiNormalIsMain
141 //=======================================================================
142 void BRepFill_LocationLaw::BiNormalIsMain()
147 //=======================================================================
148 //function : TransformInCompatibleLaw
149 //purpose : Set in continuity of laws
150 //=======================================================================
151 void BRepFill_LocationLaw::TransformInCompatibleLaw(const Standard_Real TolAngular)
154 Standard_Real First, Last, Angle;
155 Standard_Integer ipath;
157 gp_Vec V, T1, T2, N1, N2;
160 myLaws->Value(1)->GetDomain(First, Last);
162 for (ipath=2; ipath<=myLaws->Length(); ipath++) {
163 myLaws->Value(ipath-1)->D0(Last, M1, V);
164 myLaws->Value(ipath)->GetDomain(First, Last);
165 myLaws->Value(ipath)->D0(First, M2, V);
166 T1.SetXYZ(M1.Column(3));
167 T2.SetXYZ(M2.Column(3));
168 N1.SetXYZ(M1.Column(1));
169 N2.SetXYZ(M2.Column(1));
170 if (T1.IsParallel(T2, TolAngular ) &&
171 !T1.IsOpposite(T2, TolAngular)) { // Correction G0
178 alpha = T2.AngleWithRef(T1, cross);
179 gp_Ax1 axe(gp::Origin(), cross.XYZ());
180 N2.Rotate(axe, alpha);
183 if (N2.Dot(T1) > 1.e-9) {
184 cout << "Inprecision in TransformInCompatibleLaw" << endl;
185 cout << "--- T1.R(N2) = " << N2.Dot(T1) << endl;
188 tt.Rotate(axe, alpha);
189 cout << "--- T1.R(T2) = " << tt.Dot(T1) << endl;
190 cout << "--- R(N2).R(T2) = " << N2.Dot(tt) << endl;
193 Angle = N2.AngleWithRef(N1, T1);
194 Trsf.SetRotation(OZ, Angle);
196 myLaws->Value(ipath)->SetTrsf(Trsf);
200 //=======================================================================
201 //function : TransformInG0Law
202 //purpose : Set in continuity of laws
203 //=======================================================================
204 void BRepFill_LocationLaw::TransformInG0Law()
207 Standard_Real First, Last;
208 Standard_Integer ipath;
209 gp_Mat M1, M2, aux;//,Trsf
211 myLaws->Value(1)->GetDomain(First, Last);
212 for (ipath=2; ipath<=myLaws->Length(); ipath++) {
213 myLaws->Value(ipath-1)->D0(Last, M1, V);
214 myLaws->Value(ipath)->GetDomain(First, Last);
215 myLaws->Value(ipath)->D0(First, M2, V);
217 myLaws->Value(ipath)->SetTrsf(aux);
220 // Is the law periodical ?
221 if (myPath.Closed()) {
222 myLaws->Value(myLaws->Length())->D0(Last, M1, V);
223 myLaws->Value(1)->GetDomain(First, Last);
224 myLaws->Value(1)->D0(First, M2, V);
228 //=======================================================================
229 //function : DeleteTransform
230 //purpose : Remove the setting in continuity of law.
231 //=======================================================================
232 void BRepFill_LocationLaw::DeleteTransform()
236 for (Standard_Integer ii=1; ii<=myEdges->Length(); ii++) {
237 myLaws->ChangeValue(ii)->SetTrsf(Id);
242 //=======================================================================
244 //purpose : Find "Holes"
245 //=======================================================================
246 Standard_Integer BRepFill_LocationLaw::NbHoles(const Standard_Real Tol)
248 if (myDisc.IsNull()) {
249 TColStd_SequenceOfInteger Seq;
250 Standard_Integer ii, NbDisc;
251 for (ii=2, NbDisc=-1; ii<=myLaws->Length()+1; ii++) {
252 if (IsG1(ii-1, Tol, 1.e-12) == -1) {
256 NbDisc = Seq.Length();
258 myDisc = new (TColStd_HArray1OfInteger)(1, NbDisc);
259 for (ii=1; ii<=NbDisc; ii++)
260 myDisc->SetValue(ii, Seq(ii));
263 if (myDisc.IsNull()) return 0;
264 return myDisc->Length();
268 //=======================================================================
271 //=======================================================================
272 void BRepFill_LocationLaw::Holes(TColStd_Array1OfInteger& Disc) const
274 if (!myDisc.IsNull()) {
275 for (Standard_Integer ii=1; ii<=myDisc->Length(); ii++)
276 Disc(ii) = myDisc->Value(ii);
280 //=======================================================================
283 //=======================================================================
284 Standard_Integer BRepFill_LocationLaw::NbLaw() const
286 return myLaws->Length();
289 //=======================================================================
292 //=======================================================================
293 const Handle(GeomFill_LocationLaw)&
294 BRepFill_LocationLaw::Law(const Standard_Integer Index) const
296 return myLaws->Value(Index);
299 //=======================================================================
302 //=======================================================================
303 const TopoDS_Wire& BRepFill_LocationLaw::Wire() const
308 //=======================================================================
311 //=======================================================================
312 const TopoDS_Edge& BRepFill_LocationLaw::Edge(const Standard_Integer Index) const
314 return TopoDS::Edge(myEdges->Value(Index));
317 //=======================================================================
320 //=======================================================================
321 TopoDS_Vertex BRepFill_LocationLaw::Vertex(const Standard_Integer Index) const
325 if (Index <= myEdges->Length()) {
326 E = TopoDS::Edge(myEdges->Value(Index));
327 if (E.Orientation() == TopAbs_REVERSED)
328 V = TopExp::LastVertex(E);
329 else V = TopExp::FirstVertex(E);
331 else if (Index == myEdges->Length()+1) {
332 E = TopoDS::Edge(myEdges->Value(Index-1));
333 if (E.Orientation() == TopAbs_REVERSED)
334 V = TopExp::FirstVertex(E);
335 else V = TopExp::LastVertex(E);
340 //===================================================================
341 //function : PerformVertex
342 //purpose : Calculate a vertex of sweeping from a vertex of section
343 // and the index of the edge in the trajectory
344 //===================================================================
345 void BRepFill_LocationLaw::PerformVertex(const Standard_Integer Index,
346 const TopoDS_Vertex& Input,
347 const Standard_Real TolMin,
348 TopoDS_Vertex& Output,
349 const Standard_Integer ILoc) const
352 Standard_Boolean IsBary = (ILoc == 0);
353 Standard_Real First, Last;
358 if (Index>0 && Index<myLaws->Length()) {
360 myLaws->Value(Index)->GetDomain(First, Last);
361 myLaws->Value(Index)->D0(Last, M1, V1);
365 myLaws->Value(Index+1)->GetDomain(First, Last);
367 myLaws->Value(Index+1)->D0(First, M2, V2);
369 myLaws->Value(Index+1)->D0(First, M1, V1);
373 if (Index == 0 || Index == myLaws->Length()) {
374 if (!myPath.Closed() || (IsG1(Index, TolMin) != 1)) {
375 IsBary = Standard_False;
377 myLaws->Value(1)->GetDomain(First, Last);
378 myLaws->Value(1)->D0(First, M1, V1);
381 myLaws->Value(myLaws->Length())->GetDomain(First, Last);
382 myLaws->Value(myLaws->Length())->D0(Last, M1, V1);
387 myLaws->Value(myLaws->Length())->GetDomain(First, Last);
388 myLaws->Value(myLaws->Length())->D0(Last, M1, V1);
392 myLaws->Value(1)->GetDomain(First, Last);
394 myLaws->Value(1)->D0(First, M2, V2);
396 myLaws->Value(1)->D0(First, M1, V1);
401 P = BRep_Tool::Pnt(Input);
404 gp_XYZ P1(P.XYZ()), P2(P.XYZ());
410 P.ChangeCoord().SetLinearForm(0.5, P1, 0.5, P2);
412 Standard_Real Tol = P1.Modulus()/2;
414 B.MakeVertex(Output, P, Tol);
417 P.ChangeCoord() *= M1;
418 P.ChangeCoord() += V1.XYZ();
419 B.MakeVertex(Output, P, TolMin);
424 //=======================================================================
425 //function : CurvilinearBounds
427 //=======================================================================
428 void BRepFill_LocationLaw::CurvilinearBounds(const Standard_Integer Index,
429 Standard_Real& First,
430 Standard_Real& Last) const
432 First = myLength->Value(Index);
433 Last = myLength->Value(Index+1);
434 if (Last<0) { //It is required to carry out the calculation
435 Standard_Integer ii, NbE = myEdges->Length();
436 Standard_Real Length, f, l;
437 GCPnts_AbscissaPoint AbsC;
439 for (ii=1, Length=0.; ii<=NbE; ii++) {
440 myLaws->Value(ii)->GetDomain(f, l);
441 Length += AbsC.Length(myLaws->Value(ii)->GetCurve()->GetCurve(), myTol);
442 myLength->SetValue(ii+1, Length);
445 First = myLength->Value(Index);
446 Last = myLength->Value(Index+1);
450 Standard_Boolean BRepFill_LocationLaw::IsClosed() const
452 return myPath.Closed();
455 //=======================================================================
457 //purpose : Evaluate the continuity of the law by a vertex
458 //=======================================================================
460 BRepFill_LocationLaw::IsG1(const Standard_Integer Index,
461 const Standard_Real SpatialTolerance,
462 const Standard_Real AngularTolerance) const
464 gp_Vec V1, DV1, V2, DV2;
465 gp_Mat M1, M2, DM1, DM2;
466 Standard_Real First, Last, EpsNul = 1.e-12;
467 Standard_Real TolEps = SpatialTolerance;
468 Standard_Boolean Ok_D1 = Standard_False;
471 TColgp_Array1OfPnt2d Bid1 (1,1);
472 TColgp_Array1OfVec2d Bid2 (1,1);
474 if (Index>0 && Index<myLaws->Length()) {
475 myLaws->Value(Index)->GetDomain(First, Last);
476 Ok_D1 = myLaws->Value(Index)->D1(Last, M1, V1, DM1, DV1,
478 if (!Ok_D1) myLaws->Value(Index)->D0(Last, M1, V1);
480 myLaws->Value(Index+1)->GetDomain(First, Last);
482 Ok_D1 = myLaws->Value(Index+1)->D1(First, M2, V2, DM2, DV2,
484 if (!Ok_D1) myLaws->Value(Index+1)->D0(First, M2, V2);
486 E = TopoDS::Edge(myEdges->Value(Index+1));
488 if (Index == 0 || Index == myLaws->Length()) {
489 if (!myPath.Closed()) return -1;
490 myLaws->Value(myLaws->Length())->GetDomain(First, Last);
491 Ok_D1 = myLaws->Value(myLaws->Length())->D1(Last, M1, V1, DM1, DV1,
493 if (!Ok_D1) myLaws->Value(myLaws->Length())->D0(Last, M1, V1);
495 myLaws->Value(1)->GetDomain(First, Last);
497 myLaws->Value(1)->D1(First, M2, V2, DM2, DV2,
499 if (!Ok_D1) myLaws->Value(1)->D0(First, M2, V2);
501 E = TopoDS::Edge(myEdges->Value(1));
504 if (E.Orientation() == TopAbs_REVERSED)
505 V = TopExp::LastVertex(E);
507 V = TopExp::FirstVertex(E);
509 TolEps += 2*BRep_Tool::Tolerance(V);
511 Standard_Boolean isG0 = Standard_True;
512 Standard_Boolean isG1 = Standard_True;
514 if ((V1-V2).Magnitude() > TolEps) isG0 = Standard_False;
515 if (Norm(M1-M2) > SpatialTolerance) isG0 = Standard_False;
517 if (!isG0) return -1;
518 if (!Ok_D1) return 0; // No control of the derivative
520 if ( (DV1.Magnitude()>EpsNul) && (DV2.Magnitude()>EpsNul)
521 && (DV1.Angle(DV2) > AngularTolerance) ) isG1 = Standard_False;
523 // For the next, the tests are mostly empirical
524 Standard_Real Norm1 = Norm(DM1);
525 Standard_Real Norm2 = Norm(DM2);
526 // It two 2 norms are null, it is good
527 if ((Norm1 > EpsNul) || (Norm2 > EpsNul)) {
528 // otherwise the normalized matrices are compared
529 if ((Norm1 > EpsNul) && (Norm2 > EpsNul)) {
532 if (Norm(DM1 - DM2) > AngularTolerance) isG1 = Standard_False;
534 else isG1 = Standard_False; // 1 Null the other is not
542 //=======================================================================
543 //function : Parameter
545 //=======================================================================
546 void BRepFill_LocationLaw::Parameter(const Standard_Real Abcissa,
547 Standard_Integer& Index,
550 Standard_Integer iedge, NbE=myEdges->Length();
551 Standard_Boolean Trouve = Standard_False;
553 //Control that the lengths are calculated
554 if (myLength->Value(NbE+1) < 0) {
556 CurvilinearBounds(NbE, f, l);
560 for (iedge=1; iedge<=NbE && !Trouve; ) {
561 if (myLength->Value(iedge+1) >= Abcissa) {
562 Trouve = Standard_True;
569 const Handle(GeomFill_LocationLaw)& Law = myLaws->Value(iedge);
570 Law->GetDomain(f, l);
572 if (Abcissa == myLength->Value(iedge+1)) {
575 else if (Abcissa == myLength->Value(iedge)) {
581 myLaws->Value(iedge)->GetCurve()->GetCurve(),
582 Abcissa-myLength->Value(iedge), f);
583 U = AbsC.Parameter();
593 //===================================================================
595 //purpose : Position of a section, with a given curviline abscissa
596 //===================================================================
597 void BRepFill_LocationLaw::D0(const Standard_Real Abcissa,
601 Standard_Integer ind;
605 Parameter(Abcissa, ind, u);
608 myLaws->Value(ind)->D0(u, M, V);
610 fila.SetValues(M(1,1), M(1,2), M(1,3), V.X(),
611 M(2,1), M(2,2), M(2,3), V.Y(),
612 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(),