0026106: BRepMesh - revision of data model
[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 : BRepMesh_CircleTool
26 //purpose  : 
27 //=======================================================================
28 BRepMesh_CircleTool::BRepMesh_CircleTool(
29   const Handle(NCollection_IncAllocator)& theAllocator)
30 : myTolerance (Precision::PConfusion()),
31   myAllocator (theAllocator),
32   myCellFilter(10.0, theAllocator),
33   mySelector  (myTolerance, 64, theAllocator)
34 {
35 }
36
37 //=======================================================================
38 //function : BRepMesh_CircleTool
39 //purpose  : 
40 //=======================================================================
41 BRepMesh_CircleTool::BRepMesh_CircleTool(
42   const Standard_Integer                  theReservedSize,
43   const Handle(NCollection_IncAllocator)& theAllocator)
44 : myTolerance (Precision::PConfusion()),
45   myAllocator (theAllocator),
46   myCellFilter(10.0, theAllocator),
47   mySelector  (myTolerance, Max(theReservedSize, 64), theAllocator)
48 {
49 }
50
51 //=======================================================================
52 //function : bind
53 //purpose  : 
54 //=======================================================================
55 void BRepMesh_CircleTool::bind(const Standard_Integer theIndex,
56                                const gp_XY&           theLocation,
57                                const Standard_Real    theRadius)
58 {
59   BRepMesh_Circle aCirle(theLocation, theRadius);
60
61   //compute coords
62   Standard_Real aMaxX = Min(theLocation.X() + theRadius, myFaceMax.X());
63   Standard_Real aMinX = Max(theLocation.X() - theRadius, myFaceMin.X());
64   Standard_Real aMaxY = Min(theLocation.Y() + theRadius, myFaceMax.Y());
65   Standard_Real aMinY = Max(theLocation.Y() - theRadius, myFaceMin.Y());
66
67   gp_XY aMinPnt(aMinX, aMinY);
68   gp_XY aMaxPnt(aMaxX, aMaxY);
69
70   myCellFilter.Add(theIndex, aMinPnt, aMaxPnt);
71   mySelector.Bind(theIndex, aCirle);
72 }
73
74 //=======================================================================
75 //function : Bind
76 //purpose  : 
77 //=======================================================================
78 void BRepMesh_CircleTool::Bind(const Standard_Integer theIndex,
79                                const gp_Circ2d&       theCircle)
80 {
81   gp_XY         aCoord  = theCircle.Location().Coord();
82   Standard_Real aRadius = theCircle.Radius();
83   bind(theIndex, aCoord, aRadius);
84 }
85
86 //=======================================================================
87 //function : MakeCircle
88 //purpose  : 
89 //=======================================================================
90 Standard_Boolean BRepMesh_CircleTool::MakeCircle(const gp_XY&   thePoint1,
91                                                  const gp_XY&   thePoint2,
92                                                  const gp_XY&   thePoint3,
93                                                  gp_XY&         theLocation,
94                                                  Standard_Real& theRadius)
95 {
96   static const Standard_Real aPrecision   = Precision::PConfusion();
97   static const Standard_Real aSqPrecision = aPrecision * aPrecision;
98
99   gp_XY aLink1(const_cast<gp_XY&>(thePoint3).ChangeCoord(1) - const_cast<gp_XY&>(thePoint2).ChangeCoord(1),
100                const_cast<gp_XY&>(thePoint2).ChangeCoord(2) - const_cast<gp_XY&>(thePoint3).ChangeCoord(2));
101   if (aLink1.SquareModulus() < aSqPrecision)
102     return Standard_False;
103
104   gp_XY aLink2(const_cast<gp_XY&>(thePoint1).ChangeCoord(1) - const_cast<gp_XY&>(thePoint3).ChangeCoord(1),
105                const_cast<gp_XY&>(thePoint3).ChangeCoord(2) - const_cast<gp_XY&>(thePoint1).ChangeCoord(2));
106   if (aLink2.SquareModulus() < aSqPrecision)
107     return Standard_False;
108
109   gp_XY aLink3(const_cast<gp_XY&>(thePoint2).ChangeCoord(1) - const_cast<gp_XY&>(thePoint1).ChangeCoord(1),
110                const_cast<gp_XY&>(thePoint1).ChangeCoord(2) - const_cast<gp_XY&>(thePoint2).ChangeCoord(2));
111   if (aLink3.SquareModulus() < aSqPrecision)
112     return Standard_False;
113
114   const Standard_Real aD = 2 * (const_cast<gp_XY&>(thePoint1).ChangeCoord(1) * aLink1.Y() +
115                                 const_cast<gp_XY&>(thePoint2).ChangeCoord(1) * aLink2.Y() +
116                                 const_cast<gp_XY&>(thePoint3).ChangeCoord(1) * aLink3.Y());
117
118   if (Abs(aD) < gp::Resolution())
119     return Standard_False;
120
121   const Standard_Real aInvD = 1. / aD;
122   const Standard_Real aSqMod1 = thePoint1.SquareModulus();
123   const Standard_Real aSqMod2 = thePoint2.SquareModulus();
124   const Standard_Real aSqMod3 = thePoint3.SquareModulus();
125   theLocation.ChangeCoord(1) = (aSqMod1 * aLink1.Y() +
126                                 aSqMod2 * aLink2.Y() +
127                                 aSqMod3 * aLink3.Y()) * aInvD;
128
129   theLocation.ChangeCoord(2) = (aSqMod1 * aLink1.X() +
130                                 aSqMod2 * aLink2.X() +
131                                 aSqMod3 * aLink3.X()) * aInvD;
132
133   theRadius = Sqrt(Max(Max((thePoint1 - theLocation).SquareModulus(),
134                            (thePoint2 - theLocation).SquareModulus()),
135                            (thePoint3 - theLocation).SquareModulus())) + 2 * RealEpsilon();
136
137   return Standard_True;
138 }
139
140 //=======================================================================
141 //function : Bind
142 //purpose  : 
143 //=======================================================================
144 Standard_Boolean BRepMesh_CircleTool::Bind(const Standard_Integer theIndex,
145                                            const gp_XY&           thePoint1,
146                                            const gp_XY&           thePoint2,
147                                            const gp_XY&           thePoint3)
148 {
149   gp_XY aLocation;
150   Standard_Real aRadius;
151   if (!MakeCircle(thePoint1, thePoint2, thePoint3, aLocation, aRadius))
152     return Standard_False;
153
154   bind(theIndex, aLocation, aRadius);
155   return Standard_True;
156 }
157
158 //=======================================================================
159 //function : Delete
160 //purpose  : 
161 //=======================================================================
162 void BRepMesh_CircleTool::Delete(const Standard_Integer theIndex)
163 {
164   BRepMesh_Circle& aCircle = mySelector.Circle(theIndex);
165   if(aCircle.Radius() > 0.)
166     aCircle.SetRadius(-1);
167 }
168
169 //=======================================================================
170 //function : Select
171 //purpose  : 
172 //=======================================================================
173 IMeshData::ListOfInteger& BRepMesh_CircleTool::Select(const gp_XY& thePoint)
174 {
175   mySelector.SetPoint(thePoint);
176   myCellFilter.Inspect(thePoint, mySelector);
177   return mySelector.GetShotCircles();
178 }
179
180 //=======================================================================
181 //function : MocBind
182 //purpose  : 
183 //=======================================================================
184 void BRepMesh_CircleTool::MocBind(const Standard_Integer theIndex)
185 {
186   BRepMesh_Circle aNullCir(gp::Origin2d().Coord(), -1.);
187   mySelector.Bind(theIndex, aNullCir);
188 }