1 // Created on: 1999-05-11
2 // Created by: Sergei ZERTCHANINOV
3 // Copyright (c) 1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
6 // This file is part of Open CASCADE Technology software library.
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.
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
18 #include <BRep_Builder.hxx>
19 #include <BRep_GCurve.hxx>
20 #include <BRep_ListIteratorOfListOfCurveRepresentation.hxx>
21 #include <BRep_TEdge.hxx>
22 #include <BRep_Tool.hxx>
25 #include <Precision.hxx>
26 #include <ShapeFix_EdgeConnect.hxx>
27 #include <TColgp_SequenceOfXYZ.hxx>
29 #include <TopExp_Explorer.hxx>
31 #include <TopoDS_Edge.hxx>
32 #include <TopoDS_Shape.hxx>
33 #include <TopoDS_Vertex.hxx>
34 #include <TopoDS_Wire.hxx>
35 #include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
36 #include <TopTools_ListIteratorOfListOfShape.hxx>
37 #include <TopTools_ListOfShape.hxx>
39 //#define POSITION_USES_MEAN_POINT
40 //=======================================================================
41 //function : ShapeFix_EdgeConnect
42 //=======================================================================
43 ShapeFix_EdgeConnect::ShapeFix_EdgeConnect () {}
45 //=======================================================================
47 //purpose : Adds connectivity information for two edges
48 //=======================================================================
50 void ShapeFix_EdgeConnect::Add (const TopoDS_Edge& aFirst, const TopoDS_Edge& aSecond)
52 // Select vertices to connect
53 TopoDS_Vertex theFirstVertex = TopExp::LastVertex( aFirst, Standard_True );
54 TopoDS_Vertex theSecondVertex = TopExp::FirstVertex( aSecond, Standard_True );
56 // Make necessary bindings
57 if ( myVertices.IsBound( theFirstVertex ) ) {
58 // First vertex is bound - find shared vertex
59 TopoDS_Vertex theFirstShared = TopoDS::Vertex( myVertices( theFirstVertex ) );
60 if ( myVertices.IsBound( theSecondVertex ) ) {
61 // Second vertex is bound - find shared vertex
62 TopoDS_Vertex theSecondShared = TopoDS::Vertex( myVertices( theSecondVertex ) );
63 if ( !theFirstShared.IsSame(theSecondShared) ) {
65 TopTools_ListOfShape& theFirstList = myLists( theFirstShared );
66 TopTools_ListOfShape& theSecondList = myLists( theSecondShared );
67 for ( TopTools_ListIteratorOfListOfShape theIterator( theSecondList );
69 theIterator.Next() ) {
70 // Rebind shared vertex for current one
71 myVertices( theIterator.Value() ) = theFirstShared;
72 // Skip the following edge
75 // Append second list to the first one
76 theFirstList.Append( theSecondList );
77 // Unbind the second shared vertex
78 myLists.UnBind( theSecondShared );
82 // Bind second vertex with shared vertex of the first one
83 myVertices.Bind( theSecondVertex, theFirstShared );
84 // Add second vertex and second edge to the list
85 TopTools_ListOfShape& theFirstList = myLists( theFirstShared );
86 theFirstList.Append( theSecondVertex );
87 theFirstList.Append( aSecond );
91 if ( myVertices.IsBound( theSecondVertex ) ) {
92 // Second vertex is bound - find shared vertex
93 TopoDS_Vertex& theSecondShared = TopoDS::Vertex( myVertices( theSecondVertex ) );
94 // Bind first vertex with shared vertex of the second one
95 myVertices.Bind( theFirstVertex, theSecondShared );
96 // Add first vertex and first edge to the list
97 TopTools_ListOfShape& theSecondList = myLists( theSecondShared );
98 theSecondList.Append( theFirstVertex );
99 theSecondList.Append( aFirst );
102 // None is bound - create new bindings
103 myVertices.Bind( theFirstVertex, theFirstVertex );
104 myVertices.Bind( theSecondVertex, theFirstVertex );
105 TopTools_ListOfShape theNewList;
106 theNewList.Append( theFirstVertex );
107 theNewList.Append( aFirst );
108 theNewList.Append( theSecondVertex );
109 theNewList.Append( aSecond );
110 myLists.Bind( theFirstVertex, theNewList );
115 //=======================================================================
117 //purpose : Adds connectivity information for the whole shape
118 //=======================================================================
120 void ShapeFix_EdgeConnect::Add (const TopoDS_Shape& aShape)
122 for ( TopExp_Explorer expw( aShape, TopAbs_WIRE ); expw.More(); expw.Next() ) {
123 TopoDS_Wire theWire = TopoDS::Wire(expw.Current());
124 TopExp_Explorer expe( theWire, TopAbs_EDGE );
126 // Obtain the first edge and remember it
127 TopoDS_Edge theEdge = TopoDS::Edge(expe.Current());
128 TopoDS_Edge theFirst = theEdge;
130 for (; expe.More(); expe.Next()) {
131 // Obtain second edge and connect it
132 TopoDS_Edge theNext = TopoDS::Edge(expe.Current());
133 Add( theEdge, theNext );
136 // Connect first and last edges if wire is closed
137 if (theWire.Closed()) Add( theEdge, theFirst );
142 //=======================================================================
144 //purpose : Builds shared vertices
145 //=======================================================================
147 void ShapeFix_EdgeConnect::Build ()
149 TopTools_ListIteratorOfListOfShape theLIterator;
150 BRep_ListIteratorOfListOfCurveRepresentation theCIterator;
152 TColgp_SequenceOfXYZ thePositions;
154 Standard_Real theMaxDev;
155 BRep_Builder theBuilder;
157 // Iterate on shared vertices
158 for ( TopTools_DataMapIteratorOfDataMapOfShapeListOfShape theSIterator( myLists );
160 theSIterator.Next() ) {
161 TopoDS_Vertex theSharedVertex = TopoDS::Vertex( theSIterator.Key() );
162 const TopTools_ListOfShape& theList = theSIterator.Value();
164 thePositions.Clear();
166 // Iterate on edges, accumulating positions
167 for ( theLIterator.Initialize( theList );
169 theLIterator.Next() ) {
170 TopoDS_Vertex& theVertex = TopoDS::Vertex( theLIterator.Value() );
172 TopoDS_Edge& theEdge = TopoDS::Edge( theLIterator.Value() );
174 // Determine usage of curve bound points
175 TopoDS_Vertex theStart, theEnd;
176 theEdge.Orientation(TopAbs_FORWARD);
177 TopExp::Vertices( theEdge, theStart, theEnd );
178 Standard_Boolean use_start = ( theVertex.IsSame( theStart ) );
179 Standard_Boolean use_end = ( theVertex.IsSame( theEnd ) );
181 // Iterate on edge curves, accumulating positions
182 for (theCIterator.Initialize((*((Handle(BRep_TEdge)*)&theEdge.TShape()))->ChangeCurves());
183 theCIterator.More(); theCIterator.Next()) {
184 Handle(BRep_GCurve) GC = Handle(BRep_GCurve)::DownCast(theCIterator.Value());
185 if ( GC.IsNull() ) continue;
186 // Calculate vertex position for this curve
187 Standard_Real theFParam, theLParam;
188 GC->Range( theFParam, theLParam );
191 GC->D0( theFParam, thePoint );
192 thePositions.Append( thePoint.XYZ() );
195 GC->D0( theLParam, thePoint );
196 thePositions.Append( thePoint.XYZ() );
201 Standard_Integer i, theNbPos = thePositions.Length();
203 // Calculate vertex position
204 thePosition = gp_XYZ(0.,0.,0.);
206 #ifdef POSITION_USES_MEAN_POINT
207 #undef POSITION_USES_MEAN_POINT
208 for ( i = 1; i <= theNbPos; i++ ) thePosition += thePositions.Value(i);
209 if ( theNbPos > 1 ) thePosition /= theNbPos;
211 gp_XYZ theLBound(0.,0.,0.), theRBound(0.,0.,0.);
212 for ( i = 1; i <= theNbPos; i++ ) {
213 thePosition = thePositions.Value(i);
214 if ( i == 1 ) theLBound = theRBound = thePosition;
215 Standard_Real val = thePosition.X();
216 if ( val < theLBound.X() ) theLBound.SetX( val );
217 else if ( val > theRBound.X() ) theRBound.SetX( val );
218 val = thePosition.Y();
219 if ( val < theLBound.Y() ) theLBound.SetY( val );
220 else if ( val > theRBound.Y() ) theRBound.SetY( val );
221 val = thePosition.Z();
222 if ( val < theLBound.Z() ) theLBound.SetZ( val );
223 else if ( val > theRBound.Z() ) theRBound.SetZ( val );
225 if ( theNbPos > 1 ) thePosition = (theLBound + theRBound)/2.;
228 // Calculate maximal deviation
231 for ( i = 1; i <= theNbPos; i++ ) {
232 Standard_Real theDeviation = (thePosition-thePositions.Value(i)).Modulus();
233 if ( theDeviation > theMaxDev ) theMaxDev = theDeviation;
235 theMaxDev *= 1.0001; // To avoid numerical roundings
236 if ( theMaxDev < Precision::Confusion() ) theMaxDev = Precision::Confusion();
238 // Update shared vertex
239 theBuilder.UpdateVertex( theSharedVertex, gp_Pnt(thePosition), theMaxDev );
241 // Iterate on edges, adding shared vertex
242 for ( theLIterator.Initialize( theList );
244 theLIterator.Next() ) {
245 TopoDS_Vertex& theVertex = TopoDS::Vertex( theLIterator.Value() );
247 TopoDS_Edge& theEdge = TopoDS::Edge( theLIterator.Value() );
249 // Determine usage of old vertices
250 TopoDS_Vertex theStart, theEnd;
251 theEdge.Orientation(TopAbs_FORWARD);
252 TopExp::Vertices( theEdge, theStart, theEnd );
253 Standard_Boolean use_start = ( theVertex.IsSame( theStart ) );
254 Standard_Boolean use_end = ( theVertex.IsSame( theEnd ) );
256 // Prepare vertex to remove
257 TopoDS_Vertex theOldVertex;
258 if (use_start) theOldVertex = theStart; // start is preferred for closed edges
259 else theOldVertex = theEnd;
261 // Prepare vertex to add
262 TopoDS_Vertex theNewVertex;
265 TopoDS_Shape tmpshapeFwd = theSharedVertex.Oriented(TopAbs_FORWARD);
266 theNewVertex = TopoDS::Vertex(tmpshapeFwd);
269 TopoDS_Shape tmpshapeRev = theSharedVertex.Oriented(TopAbs_REVERSED);
270 theNewVertex = TopoDS::Vertex(tmpshapeRev);
272 if ( !theOldVertex.IsSame(theNewVertex) ) {
274 Standard_Boolean freeflag = theEdge.Free();
275 theEdge.Free(Standard_True); //smh
276 theBuilder.Remove( theEdge, theOldVertex );
277 theBuilder.Add( theEdge, theNewVertex );
278 if (use_start && use_end) {
279 // process special case for closed edge
280 theBuilder.Remove( theEdge, theOldVertex.Oriented(TopAbs_REVERSED) ); // remove reversed from closed edge
281 theBuilder.Add( theEdge, theNewVertex.Oriented(TopAbs_REVERSED) ); // add reversed to closed edge
283 theEdge.Free(freeflag);
288 // Clear maps after build
292 //=======================================================================
295 //=======================================================================
297 void ShapeFix_EdgeConnect::Clear ()