| 1 | // Created by: Peter KURNEV |
| 2 | // Copyright (c) 1999-2012 OPEN CASCADE SAS |
| 3 | // |
| 4 | // The content of this file is subject to the Open CASCADE Technology Public |
| 5 | // License Version 6.5 (the "License"). You may not use the content of this file |
| 6 | // except in compliance with the License. Please obtain a copy of the License |
| 7 | // at http://www.opencascade.org and read it completely before using this file. |
| 8 | // |
| 9 | // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its |
| 10 | // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France. |
| 11 | // |
| 12 | // The Original Code and all software distributed under the License is |
| 13 | // distributed on an "AS IS" basis, without warranty of any kind, and the |
| 14 | // Initial Developer hereby disclaims all such warranties, including without |
| 15 | // limitation, any warranties of merchantability, fitness for a particular |
| 16 | // purpose or non-infringement. Please see the License for the specific terms |
| 17 | // and conditions governing the rights and limitations under the License. |
| 18 | |
| 19 | |
| 20 | #include <BOPAlgo_WireSplitter.ixx> |
| 21 | |
| 22 | #include <TopoDS_Shape.hxx> |
| 23 | #include <TopoDS_Iterator.hxx> |
| 24 | #include <TopoDS_Edge.hxx> |
| 25 | #include <TopoDS.hxx> |
| 26 | #include <TopoDS_Wire.hxx> |
| 27 | |
| 28 | #include <BRep_Tool.hxx> |
| 29 | #include <BRep_Builder.hxx> |
| 30 | |
| 31 | #include <BOPCol_ListOfShape.hxx> |
| 32 | #include <BOPCol_IndexedMapOfShape.hxx> |
| 33 | #include <BOPCol_MapOfShape.hxx> |
| 34 | #include <BOPCol_IndexedDataMapOfShapeListOfShape.hxx> |
| 35 | |
| 36 | #include <BOPTools.hxx> |
| 37 | |
| 38 | |
| 39 | //======================================================================= |
| 40 | //function : |
| 41 | //purpose : |
| 42 | //======================================================================= |
| 43 | BOPAlgo_WireSplitter::BOPAlgo_WireSplitter() |
| 44 | : |
| 45 | BOPAlgo_Algo(), |
| 46 | myWES(NULL), |
| 47 | myLCB(myAllocator) |
| 48 | { |
| 49 | } |
| 50 | //======================================================================= |
| 51 | //function : |
| 52 | //purpose : |
| 53 | //======================================================================= |
| 54 | BOPAlgo_WireSplitter::BOPAlgo_WireSplitter(const Handle(NCollection_BaseAllocator)& theAllocator) |
| 55 | : |
| 56 | BOPAlgo_Algo(theAllocator), |
| 57 | myWES(NULL), |
| 58 | myLCB(myAllocator) |
| 59 | { |
| 60 | } |
| 61 | //======================================================================= |
| 62 | //function : ~ |
| 63 | //purpose : |
| 64 | //======================================================================= |
| 65 | BOPAlgo_WireSplitter::~BOPAlgo_WireSplitter() |
| 66 | { |
| 67 | } |
| 68 | //======================================================================= |
| 69 | //function : SetWES |
| 70 | //purpose : |
| 71 | //======================================================================= |
| 72 | void BOPAlgo_WireSplitter::SetWES(const BOPAlgo_WireEdgeSet& theWES) |
| 73 | { |
| 74 | myWES=(BOPAlgo_WireEdgeSet*)&theWES; |
| 75 | } |
| 76 | //======================================================================= |
| 77 | //function : WES |
| 78 | //purpose : |
| 79 | //======================================================================= |
| 80 | BOPAlgo_WireEdgeSet& BOPAlgo_WireSplitter::WES() |
| 81 | { |
| 82 | return *myWES; |
| 83 | } |
| 84 | //======================================================================= |
| 85 | // function: CheckData |
| 86 | // purpose: |
| 87 | //======================================================================= |
| 88 | void BOPAlgo_WireSplitter::CheckData() |
| 89 | { |
| 90 | myErrorStatus=0; |
| 91 | if (!myWES) { |
| 92 | myErrorStatus=10; |
| 93 | return; |
| 94 | } |
| 95 | } |
| 96 | //======================================================================= |
| 97 | //function : Perform |
| 98 | //purpose : |
| 99 | //======================================================================= |
| 100 | void BOPAlgo_WireSplitter::Perform() |
| 101 | { |
| 102 | myErrorStatus=0; |
| 103 | // |
| 104 | CheckData(); |
| 105 | if (myErrorStatus) { |
| 106 | return; |
| 107 | } |
| 108 | // |
| 109 | MakeConnexityBlocks(); |
| 110 | MakeWires(); |
| 111 | } |
| 112 | //======================================================================= |
| 113 | //function : MakeWires |
| 114 | //purpose : |
| 115 | //======================================================================= |
| 116 | void BOPAlgo_WireSplitter::MakeWires() |
| 117 | { |
| 118 | Standard_Boolean bIsRegular; |
| 119 | TopoDS_Wire aW; |
| 120 | BOPTools_ListIteratorOfListOfConnexityBlock aItCB; |
| 121 | BOPCol_ListIteratorOfListOfShape aIt; |
| 122 | // |
| 123 | aItCB.Initialize(myLCB); |
| 124 | for (; aItCB.More(); aItCB.Next()) { |
| 125 | BOPTools_ConnexityBlock& aCB=aItCB.ChangeValue(); |
| 126 | bIsRegular=aCB.IsRegular(); |
| 127 | if (bIsRegular) { |
| 128 | BOPCol_ListOfShape& aLE=aCB.ChangeShapes(); |
| 129 | BOPAlgo_WireSplitter::MakeWire(aLE, aW); |
| 130 | myWES->AddShape(aW); |
| 131 | } |
| 132 | else { |
| 133 | SplitBlock(aCB); |
| 134 | // |
| 135 | const BOPCol_ListOfShape& aLW=aCB.Loops(); |
| 136 | aIt.Initialize(aLW); |
| 137 | for (; aIt.More(); aIt.Next()) { |
| 138 | const TopoDS_Shape& aWx=aIt.Value(); |
| 139 | myWES->AddShape(aWx); |
| 140 | } |
| 141 | } |
| 142 | } |
| 143 | } |
| 144 | //======================================================================= |
| 145 | //function : MakeConnexityBlocks |
| 146 | //purpose : |
| 147 | //======================================================================= |
| 148 | void BOPAlgo_WireSplitter::MakeConnexityBlocks() |
| 149 | { |
| 150 | Standard_Boolean bRegular, bClosed; |
| 151 | Standard_Integer i, j, aNbV, aNbVS, aNbVP, k; |
| 152 | TopoDS_Iterator aItE; |
| 153 | TopoDS_Shape aER; |
| 154 | BOPCol_ListIteratorOfListOfShape aIt; |
| 155 | BOPCol_MapIteratorOfMapOfShape aItM; |
| 156 | // |
| 157 | BOPCol_IndexedDataMapOfShapeListOfShape aMVE(100, myAllocator); |
| 158 | BOPCol_IndexedMapOfShape aMVP(100, myAllocator); |
| 159 | BOPCol_IndexedMapOfShape aMEC(100, myAllocator); |
| 160 | BOPCol_MapOfShape aMER(100, myAllocator); |
| 161 | BOPCol_MapOfShape aMEP(100, myAllocator); |
| 162 | BOPCol_IndexedMapOfShape aMVAdd(100, myAllocator); |
| 163 | BOPCol_MapOfShape aMVS(100, myAllocator); |
| 164 | // |
| 165 | myLCB.Clear(); |
| 166 | // |
| 167 | const BOPCol_ListOfShape& aLSE=myWES->StartElements(); |
| 168 | aIt.Initialize(aLSE); |
| 169 | for (; aIt.More(); aIt.Next()) { |
| 170 | const TopoDS_Shape& aE=aIt.Value(); |
| 171 | if (aMEP.Add(aE)) { |
| 172 | BOPTools::MapShapesAndAncestors(aE, TopAbs_VERTEX, TopAbs_EDGE, aMVE); |
| 173 | } |
| 174 | else { |
| 175 | aMER.Add(aE); |
| 176 | } |
| 177 | } |
| 178 | // |
| 179 | // 2 |
| 180 | aNbV=aMVE.Extent(); |
| 181 | for (i=1; i<=aNbV; ++i) { |
| 182 | aNbVS=aMVS.Extent(); |
| 183 | if (aNbVS==aNbV) { |
| 184 | break; |
| 185 | } |
| 186 | // |
| 187 | const TopoDS_Shape& aV=aMVE.FindKey(i); |
| 188 | // |
| 189 | if (!aMVS.Add(aV)) { |
| 190 | continue; |
| 191 | } |
| 192 | // aMVS - globally processed vertices |
| 193 | // |
| 194 | //------------------------------------- goal: aMEC |
| 195 | aMEC.Clear(); // aMEC - edges of CB |
| 196 | aMVP.Clear(); // aMVP - vertices to process right now |
| 197 | aMVAdd.Clear(); // aMVAdd vertices to process on next step of while(1) |
| 198 | // |
| 199 | aMVP.Add(aV); |
| 200 | // |
| 201 | while(1) { |
| 202 | aNbVP=aMVP.Extent(); |
| 203 | for (k=1; k<=aNbVP; ++k) { |
| 204 | const TopoDS_Shape& aVP=aMVP(k); |
| 205 | const BOPCol_ListOfShape& aLE=aMVE.FindFromKey(aVP); |
| 206 | aIt.Initialize(aLE); |
| 207 | for (; aIt.More(); aIt.Next()) { |
| 208 | const TopoDS_Shape& aE=aIt.Value(); |
| 209 | if (aMEC.Add(aE)) { |
| 210 | aItE.Initialize(aE); |
| 211 | for (; aItE.More(); aItE.Next()) { |
| 212 | const TopoDS_Shape& aVE=aItE.Value(); |
| 213 | if (aMVS.Add(aVE)) { |
| 214 | aMVAdd.Add(aVE); |
| 215 | } |
| 216 | } |
| 217 | } |
| 218 | } |
| 219 | }//for (; aItM.More(); aItM.Next()) { |
| 220 | // |
| 221 | aNbVP=aMVAdd.Extent(); |
| 222 | if (!aNbVP) { |
| 223 | break; // from while(1) |
| 224 | } |
| 225 | // |
| 226 | aMVP.Clear(); |
| 227 | // |
| 228 | for (k=1; k<=aNbVP; ++k) { |
| 229 | const TopoDS_Shape& aVE=aMVAdd(k); |
| 230 | aMVP.Add(aVE); |
| 231 | } |
| 232 | aMVAdd.Clear(); |
| 233 | }// while(1) { |
| 234 | |
| 235 | //------------------------------------- |
| 236 | BOPTools_ConnexityBlock aCB(myAllocator); |
| 237 | BOPCol_ListOfShape& aLEC=aCB.ChangeShapes(); |
| 238 | |
| 239 | BOPCol_IndexedDataMapOfShapeListOfShape aMVER(100, myAllocator); |
| 240 | // |
| 241 | bRegular=Standard_True; |
| 242 | Standard_Integer aNbCB = aMEC.Extent(); |
| 243 | for (j = 1; j <= aNbCB; j++) { |
| 244 | aER = aMEC(j); |
| 245 | // |
| 246 | if (aMER.Contains(aER)) { |
| 247 | aER.Orientation(TopAbs_FORWARD); |
| 248 | aLEC.Append(aER); |
| 249 | aER.Orientation(TopAbs_REVERSED); |
| 250 | aLEC.Append(aER); |
| 251 | bRegular=Standard_False; |
| 252 | } |
| 253 | else { |
| 254 | aLEC.Append(aER); |
| 255 | } |
| 256 | // |
| 257 | if (bRegular) { |
| 258 | BOPTools::MapShapesAndAncestors(aER, TopAbs_VERTEX, TopAbs_EDGE, aMVER); |
| 259 | } |
| 260 | } |
| 261 | // |
| 262 | if (bRegular) { |
| 263 | Standard_Integer k, aNbVR, aNbER; |
| 264 | // |
| 265 | aNbVR=aMVER.Extent(); |
| 266 | for (k=1; k<=aNbVR; ++k) { |
| 267 | const BOPCol_ListOfShape& aLER=aMVER(k); |
| 268 | aNbER=aLER.Extent(); |
| 269 | if (aNbER==1) { |
| 270 | const TopoDS_Edge& aEx=TopoDS::Edge(aER); |
| 271 | bClosed=BRep_Tool::IsClosed(aEx, myWES->Face()); |
| 272 | if (!bClosed) { |
| 273 | bRegular=!bRegular; |
| 274 | break; |
| 275 | } |
| 276 | } |
| 277 | if (aNbER>2) { |
| 278 | bRegular=!bRegular; |
| 279 | break; |
| 280 | } |
| 281 | } |
| 282 | } |
| 283 | // |
| 284 | aCB.SetRegular(bRegular); |
| 285 | myLCB.Append(aCB); |
| 286 | } |
| 287 | } |