0024428: Implementation of LGPL license
[occt.git] / src / BRepFill / BRepFill_LocationLaw.cxx
CommitLineData
b311480e 1// Created on: 1998-01-14
2// Created by: Philippe MANGIN
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.
7fd59977 16
17#include <BRepFill_LocationLaw.ixx>
18
19#include <BRepTools_WireExplorer.hxx>
20#include <BRep_Tool.hxx>
21#include <BRep_Builder.hxx>
22#include <BRepAdaptor_Curve.hxx>
23#include <Adaptor3d_HCurve.hxx>
24#include <TopoDS.hxx>
25#include <TopoDS_Edge.hxx>
26#include <TopExp.hxx>
27#include <TopLoc_Location.hxx>
28
29#include <GeomFill_LocationLaw.hxx>
30#include <gp_Vec.hxx>
31#include <gp_Mat.hxx>
32#include <gp_XYZ.hxx>
33#include <gp_Trsf.hxx>
34#include <GCPnts_AbscissaPoint.hxx>
35#include <TColgp_Array1OfPnt2d.hxx>
36#include <TColgp_Array1OfVec2d.hxx>
37#include <TColStd_SequenceOfInteger.hxx>
38#include <Precision.hxx>
39
40
41//=======================================================================
42//function : Norm
0d969553 43//purpose : Norm of a Matrix
7fd59977 44//=======================================================================
45
46static Standard_Real Norm(const gp_Mat& M) {
47 Standard_Real R, Norme;
48 gp_XYZ Coord;
49 Coord = M.Row(1);
50 Norme = Abs(Coord.X()) + Abs(Coord.Y())+ Abs(Coord.Z());
51 Coord = M.Row(2);
52 R = Abs(Coord.X()) + Abs(Coord.Y())+ Abs(Coord.Z());
53 if (R>Norme) Norme = R;
54 Coord = M.Row(3);
55 R = Abs(Coord.X()) + Abs(Coord.Y())+ Abs(Coord.Z());
56 if (R>Norme) Norme = R;
57
58 return Norme;
59}
60
61//=======================================================================
62//function : ToG0
0d969553 63//purpose : Calculate tranformation T such as T.M2 = M1
7fd59977 64//=======================================================================
65
66static void ToG0(const gp_Mat& M1, const gp_Mat& M2, gp_Mat& T) {
67 T = M2.Inverted();
68 T *= M1;
69}
70
71//=======================================================================
72//function : BRepFill_LocationLaw
73//purpose :
74//=======================================================================
75
76void BRepFill_LocationLaw::Init(const TopoDS_Wire& Path)
77
78{
79 Standard_Integer NbEdge;
80 BRepTools_WireExplorer wexp;
81// Class BRep_Tool without fields and without Constructor :
82// BRep_Tool B;
83 TopoDS_Edge E;
84
85 myPath = Path;
86 myTol = 1.e-4;
87
88 for (NbEdge=0, wexp.Init(myPath);
89 wexp.More(); wexp.Next())
90// if (! B.Degenerated(wexp.Current())) NbEdge++;
91 if (! BRep_Tool::Degenerated(wexp.Current())) NbEdge++;
92
93
94 myLaws = new (GeomFill_HArray1OfLocationLaw)(1, NbEdge);
95 myLength = new (TColStd_HArray1OfReal) (1, NbEdge+1);
96 myLength->Init(-1.);
97 myLength->SetValue(1, 0.);
98 myEdges = new (TopTools_HArray1OfShape) (1, NbEdge);
99 myDisc.Nullify();
100 TangentIsMain();
101}
102
103//=======================================================================
104//function : GetStatus
105//purpose :
106//=======================================================================
107 GeomFill_PipeError BRepFill_LocationLaw::GetStatus() const
108{
109 Standard_Integer ii, N = myLaws->Length();
110 GeomFill_PipeError Status = GeomFill_PipeOk;
111 for (ii=1; ii<=N && (Status == GeomFill_PipeOk); ii++) {
112 Status = myLaws->Value(ii)->ErrorStatus();
113 }
114 return Status;
115}
116
117//=======================================================================
118//function : TangentIsMain
119//purpose :
120//=======================================================================
121void BRepFill_LocationLaw::TangentIsMain()
122{
123 myType = 1;
124}
125
126//=======================================================================
127//function : NormalIsMain
128//purpose :
129//=======================================================================
130void BRepFill_LocationLaw::NormalIsMain()
131{
132 myType = 2;
133}
134
135//=======================================================================
136//function : BiNormalIsMain
137//purpose :
138//=======================================================================
139void BRepFill_LocationLaw::BiNormalIsMain()
140{
141 myType = 3;
142}
143
144//=======================================================================
145//function : TransformInCompatibleLaw
0d969553 146//purpose : Set in continuity of laws
7fd59977 147//=======================================================================
148 void BRepFill_LocationLaw::TransformInCompatibleLaw(const Standard_Real TolAngular)
149{
150
151 Standard_Real First, Last, Angle;
152 Standard_Integer ipath;
153 gp_Mat Trsf, M1, M2;
154 gp_Vec V, T1, T2, N1, N2;
155 gp_XYZ OZ(0, 0, 1);
156
157 myLaws->Value(1)->GetDomain(First, Last);
158
159 for (ipath=2; ipath<=myLaws->Length(); ipath++) {
160 myLaws->Value(ipath-1)->D0(Last, M1, V);
161 myLaws->Value(ipath)->GetDomain(First, Last);
162 myLaws->Value(ipath)->D0(First, M2, V);
163 T1.SetXYZ(M1.Column(3));
164 T2.SetXYZ(M2.Column(3));
165 N1.SetXYZ(M1.Column(1));
166 N2.SetXYZ(M2.Column(1));
167 if (T1.IsParallel(T2, TolAngular ) &&
168 !T1.IsOpposite(T2, TolAngular)) { // Correction G0
169 ToG0(M1, M2, Trsf);
170 }
171 else {
172 Standard_Real alpha;
173 gp_Vec cross(T1);
174 cross.Cross(T2);
175 alpha = T2.AngleWithRef(T1, cross);
176 gp_Ax1 axe(gp::Origin(), cross.XYZ());
177 N2.Rotate(axe, alpha);
178
179#if DEB
180 if (N2.Dot(T1) > 1.e-9) {
0d969553 181 cout << "Inprecision in TransformInCompatibleLaw" << endl;
7fd59977 182 cout << "--- T1.R(N2) = " << N2.Dot(T1) << endl;
183 gp_Vec tt;
184 tt = T1;
185 tt.Rotate(axe, alpha);
186 cout << "--- T1.R(T2) = " << tt.Dot(T1) << endl;
187 cout << "--- R(N2).R(T2) = " << N2.Dot(tt) << endl;
188 }
189#endif
190 Angle = N2.AngleWithRef(N1, T1);
191 Trsf.SetRotation(OZ, Angle);
192 }
193 myLaws->Value(ipath)->SetTrsf(Trsf);
194 }
195}
196
197//=======================================================================
198//function : TransformInG0Law
0d969553 199//purpose : Set in continuity of laws
7fd59977 200//=======================================================================
201 void BRepFill_LocationLaw::TransformInG0Law()
202{
203
204 Standard_Real First, Last;
205 Standard_Integer ipath;
206 gp_Mat M1, M2, aux;//,Trsf
207 gp_Vec V;
208 myLaws->Value(1)->GetDomain(First, Last);
209 for (ipath=2; ipath<=myLaws->Length(); ipath++) {
210 myLaws->Value(ipath-1)->D0(Last, M1, V);
211 myLaws->Value(ipath)->GetDomain(First, Last);
212 myLaws->Value(ipath)->D0(First, M2, V);
213 ToG0(M1, M2, aux);
214 myLaws->Value(ipath)->SetTrsf(aux);
215 }
216
0d969553 217 // Is the law periodical ?
7fd59977 218 if (myPath.Closed()) {
219 myLaws->Value(myLaws->Length())->D0(Last, M1, V);
220 myLaws->Value(1)->GetDomain(First, Last);
221 myLaws->Value(1)->D0(First, M2, V);
222 }
223}
224
225//=======================================================================
226//function : DeleteTransform
0d969553 227//purpose : Remove the setting in continuity of law.
7fd59977 228//=======================================================================
229 void BRepFill_LocationLaw::DeleteTransform()
230{
231 gp_Mat Id;
232 Id.SetIdentity();
233 for (Standard_Integer ii=1; ii<=myEdges->Length(); ii++) {
234 myLaws->ChangeValue(ii)->SetTrsf(Id);
235 }
236 myDisc.Nullify();
237}
238
239//=======================================================================
240//function : NbHoles
0d969553 241//purpose : Find "Holes"
7fd59977 242//=======================================================================
243 Standard_Integer BRepFill_LocationLaw::NbHoles(const Standard_Real Tol)
244{
245 if (myDisc.IsNull()) {
246 TColStd_SequenceOfInteger Seq;
247 Standard_Integer ii, NbDisc;
248 for (ii=2, NbDisc=-1; ii<=myLaws->Length()+1; ii++) {
249 if (IsG1(ii-1, Tol, 1.e-12) == -1) {
250 Seq.Append(ii);
251 }
252 }
253 NbDisc = Seq.Length();
254 if ( NbDisc > 0) {
255 myDisc = new (TColStd_HArray1OfInteger)(1, NbDisc);
256 for (ii=1; ii<=NbDisc; ii++)
257 myDisc->SetValue(ii, Seq(ii));
258 }
259 }
260 if (myDisc.IsNull()) return 0;
261 return myDisc->Length();
262
263}
264
265//=======================================================================
266//function : Holes
267//purpose :
268//=======================================================================
269 void BRepFill_LocationLaw::Holes(TColStd_Array1OfInteger& Disc) const
270{
271 if (!myDisc.IsNull()) {
272 for (Standard_Integer ii=1; ii<=myDisc->Length(); ii++)
273 Disc(ii) = myDisc->Value(ii);
274 }
275}
276
277//=======================================================================
278//function : NbLaw
279//purpose :
280//=======================================================================
281 Standard_Integer BRepFill_LocationLaw::NbLaw() const
282{
283 return myLaws->Length();
284}
285
286//=======================================================================
287//function : Law
288//purpose :
289//=======================================================================
290const Handle(GeomFill_LocationLaw)&
291BRepFill_LocationLaw::Law(const Standard_Integer Index) const
292{
293 return myLaws->Value(Index);
294}
295
296//=======================================================================
297//function : Wire
298//purpose :
299//=======================================================================
300const TopoDS_Wire& BRepFill_LocationLaw::Wire() const
301{
302 return myPath;
303}
304
305//=======================================================================
306//function : Edge
307//purpose :
308//=======================================================================
309const TopoDS_Edge& BRepFill_LocationLaw::Edge(const Standard_Integer Index) const
310{
311 return TopoDS::Edge(myEdges->Value(Index));
312}
313
314//=======================================================================
315//function : Vertex
316//purpose :
317//=======================================================================
318 TopoDS_Vertex BRepFill_LocationLaw::Vertex(const Standard_Integer Index) const
319{
320 TopoDS_Edge E;
321 TopoDS_Vertex V;
322 if (Index <= myEdges->Length()) {
323 E = TopoDS::Edge(myEdges->Value(Index));
324 if (E.Orientation() == TopAbs_REVERSED)
325 V = TopExp::LastVertex(E);
326 else V = TopExp::FirstVertex(E);
327 }
328 else if (Index == myEdges->Length()+1) {
329 E = TopoDS::Edge(myEdges->Value(Index-1));
330 if (E.Orientation() == TopAbs_REVERSED)
331 V = TopExp::FirstVertex(E);
332 else V = TopExp::LastVertex(E);
333 }
334 return V;
335}
336
0d969553 337//===================================================================
7fd59977 338//function : PerformVertex
0d969553
Y
339//purpose : Calculate a vertex of sweeping from a vertex of section
340// and the index of the edge in the trajectory
341//===================================================================
7fd59977 342void BRepFill_LocationLaw::PerformVertex(const Standard_Integer Index,
343 const TopoDS_Vertex& Input,
344 const Standard_Real TolMin,
345 TopoDS_Vertex& Output,
346 const Standard_Integer ILoc) const
347{
348 BRep_Builder B;
349 Standard_Boolean IsBary = (ILoc == 0);
350 Standard_Real First, Last;
351 gp_Pnt P;
352 gp_Vec V1, V2;//, V;
353 gp_Mat M1, M2;
354
355 if (Index>0 && Index<myLaws->Length()) {
356 if (ILoc <=0) {
357 myLaws->Value(Index)->GetDomain(First, Last);
358 myLaws->Value(Index)->D0(Last, M1, V1);
359 }
360
361 if (ILoc >= 0) {
362 myLaws->Value(Index+1)->GetDomain(First, Last);
363 if (ILoc == 0)
364 myLaws->Value(Index+1)->D0(First, M2, V2);
365 else
366 myLaws->Value(Index+1)->D0(First, M1, V1);
367 }
368 }
369
370 if (Index == 0 || Index == myLaws->Length()) {
371 if (!myPath.Closed() || (IsG1(Index, TolMin) != 1)) {
372 IsBary = Standard_False;
373 if (Index == 0) {
374 myLaws->Value(1)->GetDomain(First, Last);
375 myLaws->Value(1)->D0(First, M1, V1);
376 }
377 else {
378 myLaws->Value(myLaws->Length())->GetDomain(First, Last);
379 myLaws->Value(myLaws->Length())->D0(Last, M1, V1);
380 }
381 }
382 else {
383 if (ILoc <=0) {
384 myLaws->Value(myLaws->Length())->GetDomain(First, Last);
385 myLaws->Value(myLaws->Length())->D0(Last, M1, V1);
386 }
387
388 if (ILoc >=0) {
389 myLaws->Value(1)->GetDomain(First, Last);
390 if (ILoc==0)
391 myLaws->Value(1)->D0(First, M2, V2);
392 else
393 myLaws->Value(1)->D0(First, M1, V1);
394 }
395 }
396 }
397
398 P = BRep_Tool::Pnt(Input);
399
400 if (IsBary) {
401 gp_XYZ P1(P.XYZ()), P2(P.XYZ());
402 P1 *= M1;
403 P1 += V1.XYZ();
404 P2 *= M2;
405 P2 += V2.XYZ();
406
407 P.ChangeCoord().SetLinearForm(0.5, P1, 0.5, P2);
408 P1 -= P2;
409 Standard_Real Tol = P1.Modulus()/2;
410 Tol += TolMin;
411 B.MakeVertex(Output, P, Tol);
412 }
413 else {
414 P.ChangeCoord() *= M1;
415 P.ChangeCoord() += V1.XYZ();
416 B.MakeVertex(Output, P, TolMin);
417 }
418
419}
420
421//=======================================================================
422//function : CurvilinearBounds
423//purpose :
424//=======================================================================
425void BRepFill_LocationLaw::CurvilinearBounds(const Standard_Integer Index,
426 Standard_Real& First,
427 Standard_Real& Last) const
428{
429 First = myLength->Value(Index);
430 Last = myLength->Value(Index+1);
0d969553 431 if (Last<0) { //It is required to carry out the calculation
7fd59977 432 Standard_Integer ii, NbE = myEdges->Length();
433 Standard_Real Length, f, l;
434 GCPnts_AbscissaPoint AbsC;
435
436 for (ii=1, Length=0.; ii<=NbE; ii++) {
437 myLaws->Value(ii)->GetDomain(f, l);
438 Length += AbsC.Length(myLaws->Value(ii)->GetCurve()->GetCurve(), myTol);
439 myLength->SetValue(ii+1, Length);
440 }
441
442 First = myLength->Value(Index);
443 Last = myLength->Value(Index+1);
444 }
445}
446
447 Standard_Boolean BRepFill_LocationLaw::IsClosed() const
448{
449 return myPath.Closed();
450}
451
452//=======================================================================
453//function : IsG1
0d969553 454//purpose : Evaluate the continuity of the law by a vertex
7fd59977 455//=======================================================================
456 Standard_Integer
457 BRepFill_LocationLaw::IsG1(const Standard_Integer Index,
458 const Standard_Real SpatialTolerance,
459 const Standard_Real AngularTolerance) const
460{
461 gp_Vec V1, DV1, V2, DV2;
462 gp_Mat M1, M2, DM1, DM2;
463 Standard_Real First, Last, EpsNul = 1.e-12;
464 Standard_Real TolEps = SpatialTolerance;
7fd59977 465 Standard_Boolean Ok_D1 = Standard_False;
7fd59977 466 TopoDS_Vertex V;
467 TopoDS_Edge E;
468 TColgp_Array1OfPnt2d Bid1 (1,1);
469 TColgp_Array1OfVec2d Bid2 (1,1);
470
471 if (Index>0 && Index<myLaws->Length()) {
472 myLaws->Value(Index)->GetDomain(First, Last);
473 Ok_D1 = myLaws->Value(Index)->D1(Last, M1, V1, DM1, DV1,
474 Bid1, Bid2);
475 if (!Ok_D1) myLaws->Value(Index)->D0(Last, M1, V1);
476
477 myLaws->Value(Index+1)->GetDomain(First, Last);
478 if (Ok_D1)
479 Ok_D1 = myLaws->Value(Index+1)->D1(First, M2, V2, DM2, DV2,
480 Bid1, Bid2);
481 if (!Ok_D1) myLaws->Value(Index+1)->D0(First, M2, V2);
482
483 E = TopoDS::Edge(myEdges->Value(Index+1));
484 }
485 if (Index == 0 || Index == myLaws->Length()) {
486 if (!myPath.Closed()) return -1;
487 myLaws->Value(myLaws->Length())->GetDomain(First, Last);
488 Ok_D1 = myLaws->Value(myLaws->Length())->D1(Last, M1, V1, DM1, DV1,
489 Bid1, Bid2);
490 if (!Ok_D1) myLaws->Value(myLaws->Length())->D0(Last, M1, V1);
491
492 myLaws->Value(1)->GetDomain(First, Last);
493 if (Ok_D1)
494 myLaws->Value(1)->D1(First, M2, V2, DM2, DV2,
495 Bid1, Bid2);
496 if (!Ok_D1) myLaws->Value(1)->D0(First, M2, V2);
497
498 E = TopoDS::Edge(myEdges->Value(1));
499 }
500
501 if (E.Orientation() == TopAbs_REVERSED)
502 V = TopExp::LastVertex(E);
503 else
504 V = TopExp::FirstVertex(E);
505
506 TolEps += 2*BRep_Tool::Tolerance(V);
507
508 Standard_Boolean isG0 = Standard_True;
509 Standard_Boolean isG1 = Standard_True;
510
511 if ((V1-V2).Magnitude() > TolEps) isG0 = Standard_False;
512 if (Norm(M1-M2) > SpatialTolerance) isG0 = Standard_False;
513
514 if (!isG0) return -1;
0d969553 515 if (!Ok_D1) return 0; // No control of the derivative
7fd59977 516
517 if ( (DV1.Magnitude()>EpsNul) && (DV2.Magnitude()>EpsNul)
518 && (DV1.Angle(DV2) > AngularTolerance) ) isG1 = Standard_False;
519
0d969553 520 // For the next, the tests are mostly empirical
7fd59977 521 Standard_Real Norm1 = Norm(DM1);
522 Standard_Real Norm2 = Norm(DM2);
0d969553 523 // It two 2 norms are null, it is good
7fd59977 524 if ((Norm1 > EpsNul) || (Norm2 > EpsNul)) {
0d969553 525 // otherwise the normalized matrices are compared
7fd59977 526 if ((Norm1 > EpsNul) && (Norm2 > EpsNul)) {
527 DM1 /= Norm1;
528 DM2 /= Norm2;
529 if (Norm(DM1 - DM2) > AngularTolerance) isG1 = Standard_False;
530 }
0d969553 531 else isG1 = Standard_False; // 1 Null the other is not
7fd59977 532 }
533
534 if (isG1) return 1;
535 else return 0;
536}
537
538
539//=======================================================================
540//function : Parameter
541//purpose :
542//=======================================================================
543 void BRepFill_LocationLaw::Parameter(const Standard_Real Abcissa,
544 Standard_Integer& Index,
545 Standard_Real& U)
546{
547 Standard_Integer iedge, NbE=myEdges->Length();
548 Standard_Boolean Trouve = Standard_False;
549
0d969553 550 //Control that the lengths are calculated
7fd59977 551 if (myLength->Value(NbE+1) < 0) {
552 Standard_Real f, l;
553 CurvilinearBounds(NbE, f, l);
554 }
555
0d969553 556 // Find the interval
7fd59977 557 for (iedge=1; iedge<=NbE && !Trouve; ) {
558 if (myLength->Value(iedge+1) >= Abcissa) {
559 Trouve = Standard_True;
560 }
561 else iedge++;
562 }
563
564 if (Trouve) {
565 Standard_Real f, l;
566 const Handle(GeomFill_LocationLaw)& Law = myLaws->Value(iedge);
567 Law->GetDomain(f, l);
568
569 if (Abcissa == myLength->Value(iedge+1)) {
570 U = l;
571 }
572 else if (Abcissa == myLength->Value(iedge)) {
573 U = f;
574 }
575 else {
576 GCPnts_AbscissaPoint
577 AbsC(myTol,
578 myLaws->Value(iedge)->GetCurve()->GetCurve(),
579 Abcissa-myLength->Value(iedge), f);
580 U = AbsC.Parameter();
581 }
582 Index = iedge;
583 }
584 else {
585 Index = 0;
586 }
587}
588
589
0d969553 590//===================================================================
7fd59977 591//function : D0
0d969553
Y
592//purpose : Position of a section, with a given curviline abscissa
593//===================================================================
7fd59977 594 void BRepFill_LocationLaw::D0(const Standard_Real Abcissa,
595 TopoDS_Shape& W)
596{
597 Standard_Real u;
598 Standard_Integer ind;
599 gp_Mat M;
600 gp_Vec V;
601
602 Parameter(Abcissa, ind, u);
603 if (ind != 0) {
604 // Positionement
605 myLaws->Value(ind)->D0(u, M, V);
606 gp_Trsf fila;
607 fila.SetValues(M(1,1), M(1,2), M(1,3), V.X(),
608 M(2,1), M(2,2), M(2,3), V.Y(),
609 M(3,1), M(3,2), M(3,3), V.Z(),
610 1.e-12, 1.e-14);
611 TopLoc_Location Loc(fila);
612 W.Location(Loc.Multiplied(W.Location()));
613 }
614 else {
615 W.Nullify();
616#if DEB
0d969553 617 cout << "BRepFill_LocationLaw::D0 : Attention position out of limits"
7fd59977 618 << endl;
619#endif
620 }
621}
622
623//=======================================================================
624//function : Abscissa
0d969553 625//purpose : Calculate the abscissa of a point
7fd59977 626//=======================================================================
627 Standard_Real BRepFill_LocationLaw::Abscissa(const Standard_Integer Index,
628 const Standard_Real Param)
629{
630 GCPnts_AbscissaPoint AbsC;
631 Standard_Real Length = myLength->Value(Index);
632 if (Length < 0) {
633 Standard_Real bid;
634 CurvilinearBounds(Index, bid, Length);
635 }
636
637 Length += AbsC.Length(myLaws->Value(Index)->GetCurve()->GetCurve(),
638 myLaws->Value(Index)->GetCurve()->FirstParameter(),
639 Param, myTol);
640 return Length;
641}