| 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, 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, 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())) + aPrecision; |
| 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 | } |