0022048: Visualization, AIS_InteractiveContext - single object selection should alway...
[occt.git] / src / ShapeCustom / ShapeCustom_Curve2d.cxx
CommitLineData
b311480e 1// Created on: 2001-12-20
2// Created by: Pavel TELKOV
973c2be1 3// Copyright (c) 2001-2014 OPEN CASCADE SAS
b311480e 4//
973c2be1 5// This file is part of Open CASCADE Technology software library.
b311480e 6//
d5f74e42 7// This library is free software; you can redistribute it and/or modify it under
8// the terms of the GNU Lesser General Public License version 2.1 as published
973c2be1 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.
b311480e 12//
973c2be1 13// Alternatively, this file may be used under the terms of Open CASCADE
14// commercial license or contractual agreement.
7fd59977 15
16// Last modification:
17
42cf5bc1 18#include <ElCLib.hxx>
19#include <Geom2d_BezierCurve.hxx>
20#include <Geom2d_BSplineCurve.hxx>
21#include <Geom2d_Curve.hxx>
22#include <Geom2d_Line.hxx>
7fd59977 23#include <gp_Dir2d.hxx>
24#include <gp_Lin2d.hxx>
25#include <gp_Pnt2d.hxx>
42cf5bc1 26#include <gp_Vec2d.hxx>
7fd59977 27#include <Precision.hxx>
42cf5bc1 28#include <ShapeCustom_Curve2d.hxx>
29#include <Standard_ErrorHandler.hxx>
7fd59977 30
31//=======================================================================
32//function : GetLine
33//purpose : static
34//=======================================================================
35static gp_Lin2d GetLine (const gp_Pnt2d& P1, const gp_Pnt2d& P2,
36 const Standard_Real c1, Standard_Real& cf, Standard_Real& cl)
37{
38 gp_Vec2d avec (P1,P2);
39 gp_Dir2d adir (avec);
40 gp_Lin2d alin (P1,adir);
41 alin.SetLocation (ElCLib::Value (c1, alin));
42 cf = ElCLib::Parameter (alin, P1);
43 cl = ElCLib::Parameter (alin, P2);
44 return alin;
45}
46
47
48//=======================================================================
49//function : IsLinear
50//purpose : static
51//=======================================================================
52
53Standard_Boolean ShapeCustom_Curve2d::IsLinear(const TColgp_Array1OfPnt2d& thePoles,
54 const Standard_Real tolerance,
55 Standard_Real& Deviation)
56{
57 Standard_Integer nbPoles = thePoles.Length();
58 if(nbPoles < 2)
59 return Standard_False;
60
61 Standard_Real dMax = 0;
62 Standard_Integer iMax1=0,iMax2=0;
63
64 Standard_Integer i;
65 for(i = 1; i < nbPoles; i++)
66 for(Standard_Integer j = i+1; j <= nbPoles; j++) {
67 Standard_Real dist = thePoles(i).SquareDistance(thePoles(j));
68 if(dist > dMax) {
69 dMax = dist;
70 iMax1 = i;
71 iMax2 = j;
72 }
73 }
74
75 Standard_Real dPreci = Precision::PConfusion()*Precision::PConfusion();
76 if(dMax < dPreci)
77 return Standard_False;
78
79 Standard_Real tol2 = tolerance*tolerance;
80 gp_Vec2d avec (thePoles(iMax1),thePoles(iMax2));
81 gp_Dir2d adir (avec);
82 gp_Lin2d alin (thePoles(iMax1),adir);
83
84 Standard_Real aMax = 0.;
85 for(i = 1; i <= nbPoles; i++) {
86 Standard_Real dist = alin.SquareDistance(thePoles(i));
87 if(dist > tol2)
88 return Standard_False;
89 if(dist > aMax)
90 aMax = dist;
91 }
92 Deviation = sqrt(aMax);
93
94 return Standard_True;
95}
96
97//=======================================================================
98//function : ConvertToLine2d
99//purpose : static
100//=======================================================================
101
102Handle(Geom2d_Line) ShapeCustom_Curve2d::ConvertToLine2d (const Handle(Geom2d_Curve)& theCurve,
103 const Standard_Real c1,
104 const Standard_Real c2,
105 const Standard_Real theTolerance,
106 Standard_Real& cf,
107 Standard_Real& cl,
108 Standard_Real& theDeviation)
109{
110 Handle(Geom2d_Line) aLine2d;
111 gp_Pnt2d P1 = theCurve->Value(c1);
112 gp_Pnt2d P2 = theCurve->Value(c2);
113 Standard_Real dPreci = theTolerance*theTolerance;
114 if(P1.SquareDistance(P2) < dPreci)
115 return aLine2d; // it is not a line
116
117 Handle(Geom2d_BSplineCurve) bsc = Handle(Geom2d_BSplineCurve)::DownCast(theCurve);
118 if (!bsc.IsNull()) {
119 Standard_Integer nbPoles = bsc->NbPoles();
120 TColgp_Array1OfPnt2d Poles(1,nbPoles);
121 bsc->Poles(Poles);
122 if(!ShapeCustom_Curve2d::IsLinear(Poles,theTolerance,theDeviation))
123 return aLine2d; // non
124 gp_Lin2d alin = GetLine (P1,P2,c1,cf,cl);
125 aLine2d = new Geom2d_Line (alin);
126 return aLine2d;
127 }
128
129 Handle(Geom2d_BezierCurve) bzc = Handle(Geom2d_BezierCurve)::DownCast(theCurve);
130 if (!bzc.IsNull()) {
131 Standard_Integer nbPoles = bzc->NbPoles();
132 TColgp_Array1OfPnt2d Poles(1,nbPoles);
133 bzc->Poles(Poles);
134 if(!ShapeCustom_Curve2d::IsLinear(Poles,theTolerance,theDeviation))
135 return aLine2d; // non
136 gp_Lin2d alin = GetLine (P1,P2,c1,cf,cl);
137 aLine2d = new Geom2d_Line (alin);
138 return aLine2d;
139 }
140
141 return aLine2d;
142}
143
144//=======================================================================
145//function : SimplifyBSpline2d
146//purpose :
147//=======================================================================
148
149Standard_Boolean ShapeCustom_Curve2d::SimplifyBSpline2d (Handle(Geom2d_BSplineCurve)& theBSpline2d,
150 const Standard_Real theTolerance)
151{
152 Standard_Integer aInitNbK;
153 Standard_Integer NbK = aInitNbK = theBSpline2d->NbKnots();
154 // search knot to remove
155 Standard_Boolean IsToRemove = Standard_True;
156 Standard_Integer aKnotIndx = NbK-1;
157 while (IsToRemove && NbK > 2)
158 {
159 Standard_Integer aMult = theBSpline2d->Multiplicity(aKnotIndx);
160 Standard_Integer DegMult = theBSpline2d->Degree() - aMult;
161 if ((DegMult > 1) && theBSpline2d->IsCN(DegMult))
162 {
163 Standard_Real U = theBSpline2d->Knot(aKnotIndx);
164 gp_Vec2d aVec1 = theBSpline2d->LocalDN(U, aKnotIndx-1, aKnotIndx, DegMult);
165 gp_Vec2d aVec2 = theBSpline2d->LocalDN(U, aKnotIndx, aKnotIndx+1, DegMult);
166 // check the derivations are have the "same" angle
167 if (aVec1.IsParallel(aVec2, Precision::Angular()))
168 {
169 // remove knot
170 try
171 {
172 OCC_CATCH_SIGNALS
173 theBSpline2d->RemoveKnot(aKnotIndx,
174 aMult-1,
175 theTolerance);
176 }
177 catch(Standard_Failure)
178 {
179 }
180 }
181 }
182 aKnotIndx--;
183
184 NbK = theBSpline2d->NbKnots();
185 if (aKnotIndx == 1 || aKnotIndx == NbK)
186 IsToRemove = Standard_False;
187 }
188 return (aInitNbK > NbK);
189}