cf2c15aa70fdd59fdc736673adbb762f64e9817c
[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.ixx>
18 #include <gp_XY.hxx>
19 #include <Precision.hxx>
20 #include <BRepMesh_Circ.hxx>
21 #include <BRepMesh_CircleInspector.hxx>
22 #include <BRepMesh_BaseAllocator.hxx>
23
24
25 //=======================================================================
26 //function : BRepMesh_CircleInspector
27 //purpose  : Constructor
28 //=======================================================================
29
30 BRepMesh_CircleInspector::BRepMesh_CircleInspector (Standard_Real theTol,
31                                                     Standard_Integer nbComp,
32                                                     const BRepMesh_BaseAllocator& theAlloc)
33                                                     : myTol(theTol*theTol),
34                                                     myResInd(theAlloc),
35                                                     myInitCircle(nbComp)
36 {
37   //  myTol = theTol*theTol;
38 }
39
40 //=======================================================================
41 //function : Inspect
42 //purpose  : 
43 //
44 //=======================================================================
45 NCollection_CellFilter_Action BRepMesh_CircleInspector::Inspect (const Standard_Integer theTarget)
46 {
47   const BRepMesh_Circ& Circ = myInitCircle(theTarget);
48   Standard_Real R = Circ.Radius();
49   if(R < 0)
50     return CellFilter_Purge;
51   Standard_Real dx,dy;
52   const gp_XY& aLoc=Circ.Location();
53   dx=myCurrent.X()-aLoc.X();
54   dy=myCurrent.Y()-aLoc.Y();
55   if ((dx*dx+dy*dy)-(R*R) <= myTol)
56     myResInd.Append(theTarget);
57   return CellFilter_Keep;
58 }
59
60
61 //=======================================================================
62 //function : BRepMesh_CircleTool
63 //purpose  : 
64 //=======================================================================
65 BRepMesh_CircleTool::BRepMesh_CircleTool(const BRepMesh_BaseAllocator& theAlloc)
66 : Tolerance(Precision::PConfusion()),
67 Allocator(theAlloc),
68 CellFilter(10, theAlloc),
69 Selector(Tolerance,64,theAlloc)
70 {
71   Tolerance=Tolerance*Tolerance;
72 }
73
74 //=======================================================================
75 //function : BRepMesh_CircleTool
76 //purpose  : 
77 //=======================================================================
78 BRepMesh_CircleTool::BRepMesh_CircleTool(const Standard_Integer nbComp,
79                                          const BRepMesh_BaseAllocator& theAlloc)
80                                          : Tolerance(Precision::PConfusion()),
81                                          Allocator(theAlloc),
82                                          CellFilter(10, theAlloc),
83                                          Selector(Tolerance,Max(nbComp,64),theAlloc)
84 {
85   Tolerance=Tolerance*Tolerance;
86 }
87
88
89 //=======================================================================
90 //function : Initialize
91 //purpose  : 
92 //=======================================================================
93 void BRepMesh_CircleTool::Initialize(const Standard_Integer /*nbComp*/)
94 {
95   Tolerance=Precision::PConfusion();
96   Tolerance=Tolerance*Tolerance;
97 }
98
99 void BRepMesh_CircleTool::SetCellSize(const Standard_Real theSize)
100 {
101   CellFilter.Reset(theSize, Allocator);
102 }
103
104 void BRepMesh_CircleTool::SetCellSize(const Standard_Real theXSize, 
105                                       const Standard_Real theYSize)
106 {
107   Standard_Real aCellSize[2];
108   aCellSize[0] = theXSize;
109   aCellSize[1] = theYSize;
110
111   CellFilter.Reset(aCellSize, Allocator);
112 }
113
114
115 void BRepMesh_CircleTool::SetMinMaxSize(const gp_XY& theMin,
116                                         const gp_XY& theMax)
117 {
118   FaceMin = theMin;
119   FaceMax = theMax;
120 }
121
122 //=======================================================================
123 //function : Add
124 //purpose  : 
125 //=======================================================================
126 void  BRepMesh_CircleTool::Add(const gp_Circ2d& theCirc,
127                                const Standard_Integer theIndex)
128 {
129   gp_XY aCoord(theCirc.Location().Coord());
130   Standard_Real R = theCirc.Radius();
131   BRepMesh_Circ aCir(aCoord, R);
132
133   //compute coords
134   Standard_Real xMax=Min(aCoord.X()+R,FaceMax.X());
135   Standard_Real xMin=Max(aCoord.X()-R,FaceMin.X());
136   Standard_Real yMax=Min(aCoord.Y()+R,FaceMax.Y());
137   Standard_Real yMin=Max(aCoord.Y()-R,FaceMin.Y());
138
139   gp_XY MinPnt(xMin,yMin);
140   gp_XY MaxPnt(xMax,yMax);
141
142   CellFilter.Add(theIndex, MinPnt, MaxPnt);
143   Selector.Add(theIndex, aCir);
144 }
145
146 //=======================================================================
147 //function : Add
148 //purpose  : 
149 //=======================================================================
150 Standard_Boolean BRepMesh_CircleTool::Add(const gp_XY& p1,
151                                           const gp_XY& p2,
152                                           const gp_XY& p3,
153                                           const Standard_Integer theIndex)
154 {
155   gp_XY m1((p1.X()+p2.X())/2., (p1.Y()+p2.Y())/2.);
156   gp_XY m2((p2.X()+p3.X())/2., (p2.Y()+p3.Y())/2.);
157   gp_XY m3((p3.X()+p1.X())/2., (p3.Y()+p1.Y())/2.);
158   Standard_Real dx=m1.X()-m2.X();
159   Standard_Real dy=m1.Y()-m2.Y();
160   Standard_Real d12=(dx*dx)+(dy*dy);
161   dx=m2.X()-m3.X();
162   dy=m2.Y()-m3.Y();
163   Standard_Real d23=(dx*dx)+(dy*dy);
164   dx=m3.X()-m1.X();
165   dy=m3.Y()-m1.Y();
166   Standard_Real d31=(dx*dx)+(dy*dy);
167   gp_XY pl11, pl12, pl21, pl22;
168
169   if (d12>d23 && d12>d31) {
170     dy=p2.Y()-p1.Y();
171     dx=p1.X()-p2.X();
172     if (dy!=0. || dx!=0.) {
173       pl11 = m1;
174       pl12 = gp_XY(dy, dx);
175     }
176     else return Standard_False;
177
178     dy=p3.Y()-p2.Y();
179     dx=p2.X()-p3.X();
180     if (dy!=0. || dx!=0.) {
181       pl21 = m2;
182       pl22 = gp_XY(dy, dx);
183     }
184     else return Standard_False;
185   }
186   else {
187     if (d23>d31) {
188       dy=p3.Y()-p2.Y();
189       dx=p2.X()-p3.X();
190       if (dy!=0. || dx!=0.) {
191         pl11 = m2;
192         pl12 = gp_XY(dy, dx);
193       }
194       else return Standard_False;
195
196       dy=p1.Y()-p3.Y();
197       dx=p3.X()-p1.X();
198       if (dy!=0. || dx!=0.) {
199         pl21 = m3;
200         pl22 = gp_XY(dy, dx);
201       }
202       else return Standard_False;
203     }
204     else {
205       dy=p1.Y()-p3.Y();
206       dx=p3.X()-p1.X();
207       if (dy!=0. || dx!=0.) {
208         pl11 = m3;
209         pl12 = gp_XY(dy, dx);
210       }
211       else return Standard_False;
212
213       dy=p2.Y()-p1.Y();
214       dx=p1.X()-p2.X();
215       if (dy!=0. || dx!=0.) {
216         pl21 = m1;
217         pl22 = gp_XY(dy, dx);
218       }
219       else return Standard_False;
220     }
221   }
222
223   gp_XY aVecO1O2 = pl21 - pl11;
224   Standard_Real aCrossD1D2 = pl12 ^ pl22;
225   Standard_Real theSinAngle = Abs(aCrossD1D2);
226   if (theSinAngle < gp::Resolution())
227     return Standard_False;
228   Standard_Real theParam1 = (aVecO1O2 ^ pl22) / aCrossD1D2;
229   gp_XY pInt = pl11+pl12*theParam1;
230   dx=p1.X()-pInt.X();
231   dy=p1.Y()-pInt.Y();
232   Standard_Real R = Sqrt(dx*dx+dy*dy);
233   BRepMesh_Circ aCir(pInt, R);
234
235   //compute coords
236   Standard_Real xMax=Min(pInt.X()+R,FaceMax.X());
237   Standard_Real xMin=Max(pInt.X()-R,FaceMin.X());
238   Standard_Real yMax=Min(pInt.Y()+R,FaceMax.Y());
239   Standard_Real yMin=Max(pInt.Y()-R,FaceMin.Y());
240
241   gp_XY MinPnt(xMin,yMin);
242   gp_XY MaxPnt(xMax,yMax);    
243
244   CellFilter.Add(theIndex, MinPnt, MaxPnt);
245
246   Selector.Add(theIndex, aCir);
247   return Standard_True;
248 }
249
250 //=======================================================================
251 //function : Delete
252 //purpose  : 
253 //=======================================================================
254 void  BRepMesh_CircleTool::Delete(const Standard_Integer theIndex)
255 {
256   BRepMesh_Circ& Circ = Selector.GetCirc(theIndex);
257   if(Circ.Radius() > 0.) {
258     Circ.SetRadius(-1);
259   }
260 }
261
262 //=======================================================================
263 //function : Select
264 //purpose  : 
265 //=======================================================================
266 BRepMesh_ListOfInteger&  BRepMesh_CircleTool::Select(const gp_XY& thePnt)
267 {
268   Selector.ClerResList();
269   Selector.SetCurrent(thePnt);
270   CellFilter.Inspect (thePnt, Selector);
271   return Selector.GetCoincidentInd();
272 }
273
274 void BRepMesh_CircleTool::MocAdd(const Standard_Integer theIndex)
275 {
276   gp_XY nullPnt(0.,0.);
277   BRepMesh_Circ theNullCir(nullPnt, -1.);
278   Selector.Add(theIndex, theNullCir);
279 }