0027119: Regression: Draw command "incmesh" hangs on the attacheced face.
[occt.git] / src / BRepMesh / BRepMesh_CircleTool.cxx
1 // Created on: 1993-06-15
2 // Created by: Didier PIFFAULT
3 // Copyright (c) 1993-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
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.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17 #include <BRepMesh_CircleTool.hxx>
18 #include <BRepMesh_GeomTool.hxx>
19 #include <gp_Circ2d.hxx>
20 #include <Precision.hxx>
21 #include <BRepMesh_Circle.hxx>
22 #include <BRepMesh_CircleInspector.hxx>
23
24 //=======================================================================
25 //function : Inspect
26 //purpose  : 
27 //=======================================================================
28 NCollection_CellFilter_Action BRepMesh_CircleInspector::Inspect(
29   const Standard_Integer theTargetIndex)
30 {
31   const BRepMesh_Circle& aCircle = myCircles(theTargetIndex);
32   Standard_Real aRadius = aCircle.Radius();
33   if(aRadius < 0.)
34     return CellFilter_Purge;
35
36   const gp_XY& aLoc = aCircle.Location();
37
38   if ((myPoint - aLoc).SquareModulus() - (aRadius * aRadius) <= myTolerance)
39     myResIndices.Append(theTargetIndex);
40
41   return CellFilter_Keep;
42 }
43
44
45 //=======================================================================
46 //function : BRepMesh_CircleTool
47 //purpose  : 
48 //=======================================================================
49 BRepMesh_CircleTool::BRepMesh_CircleTool(
50   const Handle(NCollection_IncAllocator)& theAllocator)
51 : myTolerance (Precision::PConfusion() * Precision::PConfusion()),
52   myAllocator (theAllocator),
53   myCellFilter(10.0, theAllocator),
54   mySelector  (myTolerance, 64, theAllocator)
55 {
56 }
57
58 //=======================================================================
59 //function : BRepMesh_CircleTool
60 //purpose  : 
61 //=======================================================================
62 BRepMesh_CircleTool::BRepMesh_CircleTool(
63   const Standard_Integer                  theReservedSize,
64   const Handle(NCollection_IncAllocator)& theAllocator)
65 : myTolerance (Precision::PConfusion() * Precision::PConfusion()),
66   myAllocator (theAllocator),
67   myCellFilter(10.0, theAllocator),
68   mySelector  (myTolerance, Max(theReservedSize, 64), theAllocator)
69 {
70 }
71
72 //=======================================================================
73 //function : bind
74 //purpose  : 
75 //=======================================================================
76 void BRepMesh_CircleTool::bind(const Standard_Integer theIndex,
77                                const gp_XY&           theLocation,
78                                const Standard_Real    theRadius)
79 {
80   BRepMesh_Circle aCirle(theLocation, theRadius);
81
82   //compute coords
83   Standard_Real aMaxX = Min(theLocation.X() + theRadius, myFaceMax.X());
84   Standard_Real aMinX = Max(theLocation.X() - theRadius, myFaceMin.X());
85   Standard_Real aMaxY = Min(theLocation.Y() + theRadius, myFaceMax.Y());
86   Standard_Real aMinY = Max(theLocation.Y() - theRadius, myFaceMin.Y());
87
88   gp_XY aMinPnt(aMinX, aMinY);
89   gp_XY aMaxPnt(aMaxX, aMaxY);
90
91   myCellFilter.Add(theIndex, aMinPnt, aMaxPnt);
92   mySelector.Bind(theIndex, aCirle);
93 }
94
95 //=======================================================================
96 //function : Bind
97 //purpose  : 
98 //=======================================================================
99 void BRepMesh_CircleTool::Bind(const Standard_Integer theIndex,
100                                const gp_Circ2d&       theCircle)
101 {
102   gp_XY         aCoord  = theCircle.Location().Coord();
103   Standard_Real aRadius = theCircle.Radius();
104   bind(theIndex, aCoord, aRadius);
105 }
106
107 //=======================================================================
108 //function : MakeCircle
109 //purpose  : 
110 //=======================================================================
111 Standard_Boolean BRepMesh_CircleTool::MakeCircle(const gp_XY&   thePoint1,
112                                                  const gp_XY&   thePoint2,
113                                                  const gp_XY&   thePoint3,
114                                                  gp_XY&         theLocation,
115                                                  Standard_Real& theRadius)
116 {
117   static const Standard_Real aPrecision   = Precision::PConfusion();
118   static const Standard_Real aSqPrecision = aPrecision * aPrecision;
119
120   if ((thePoint1 - thePoint3).SquareModulus() < aSqPrecision)
121     return Standard_False;
122
123   gp_XY aLink1(thePoint2 - thePoint1);
124   if (aLink1.SquareModulus() < aSqPrecision)
125     return Standard_False;
126
127   gp_XY aLink2(thePoint3 - thePoint2);
128   if (aLink2.SquareModulus() < aSqPrecision)
129     return Standard_False;
130
131   gp_XY aMidPnt1 = (thePoint1 + thePoint2) / 2.;
132   gp_XY aNorm1   = gp_XY(aLink1.Y(), -aLink1.X());
133   aNorm1.Add(aMidPnt1);
134
135   if (aLink2.SquareModulus() < aSqPrecision)
136     return Standard_False;
137
138   gp_XY aMidPnt2 = (thePoint2 + thePoint3) / 2.;
139   gp_XY aNorm2   = gp_XY(aLink2.Y(), -aLink2.X());
140   aNorm2.Add(aMidPnt2);
141
142   gp_XY aIntPnt;
143   Standard_Real aParam[2];
144   BRepMesh_GeomTool::IntFlag aIntFlag = 
145     BRepMesh_GeomTool::IntLinLin(aMidPnt1, aNorm1,
146       aMidPnt2, aNorm2, aIntPnt, aParam);
147
148   if (aIntFlag != BRepMesh_GeomTool::Cross)
149     return Standard_False;
150
151   theLocation = aIntPnt;
152
153   theRadius = Sqrt(Max(Max((thePoint1 - aIntPnt).SquareModulus(), 
154                            (thePoint2 - aIntPnt).SquareModulus()),
155                            (thePoint3 - aIntPnt).SquareModulus())) + 2 * RealEpsilon();
156
157   return Standard_True;
158 }
159
160 //=======================================================================
161 //function : Bind
162 //purpose  : 
163 //=======================================================================
164 Standard_Boolean BRepMesh_CircleTool::Bind(const Standard_Integer theIndex,
165                                            const gp_XY&           thePoint1,
166                                            const gp_XY&           thePoint2,
167                                            const gp_XY&           thePoint3)
168 {
169   gp_XY aLocation;
170   Standard_Real aRadius;
171   if (!MakeCircle(thePoint1, thePoint2, thePoint3, aLocation, aRadius))
172     return Standard_False;
173
174   bind(theIndex, aLocation, aRadius);
175   return Standard_True;
176 }
177
178 //=======================================================================
179 //function : Delete
180 //purpose  : 
181 //=======================================================================
182 void BRepMesh_CircleTool::Delete(const Standard_Integer theIndex)
183 {
184   BRepMesh_Circle& aCircle = mySelector.Circle(theIndex);
185   if(aCircle.Radius() > 0.)
186     aCircle.SetRadius(-1);
187 }
188
189 //=======================================================================
190 //function : Select
191 //purpose  : 
192 //=======================================================================
193 BRepMesh::ListOfInteger& BRepMesh_CircleTool::Select(const gp_XY& thePoint)
194 {
195   mySelector.SetPoint(thePoint);
196   myCellFilter.Inspect(thePoint, mySelector);
197   return mySelector.GetShotCircles();
198 }
199
200 //=======================================================================
201 //function : MocBind
202 //purpose  : 
203 //=======================================================================
204 void BRepMesh_CircleTool::MocBind(const Standard_Integer theIndex)
205 {
206   BRepMesh_Circle aNullCir(gp::Origin2d().Coord(), -1.);
207   mySelector.Bind(theIndex, aNullCir);
208 }