mirror of
https://github.com/Open-Cascade-SAS/OCCT.git
synced 2026-05-11 10:10:56 +08:00
307 lines
11 KiB
C++
Executable File
307 lines
11 KiB
C++
Executable File
// Created on: 1999-05-11
|
|
// Created by: Sergei ZERTCHANINOV
|
|
// Copyright (c) 1999 Matra Datavision
|
|
// Copyright (c) 1999-2012 OPEN CASCADE SAS
|
|
//
|
|
// The content of this file is subject to the Open CASCADE Technology Public
|
|
// License Version 6.5 (the "License"). You may not use the content of this file
|
|
// except in compliance with the License. Please obtain a copy of the License
|
|
// at http://www.opencascade.org and read it completely before using this file.
|
|
//
|
|
// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
|
|
// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
|
|
//
|
|
// The Original Code and all software distributed under the License is
|
|
// distributed on an "AS IS" basis, without warranty of any kind, and the
|
|
// Initial Developer hereby disclaims all such warranties, including without
|
|
// limitation, any warranties of merchantability, fitness for a particular
|
|
// purpose or non-infringement. Please see the License for the specific terms
|
|
// and conditions governing the rights and limitations under the License.
|
|
|
|
|
|
#include <ShapeFix_EdgeConnect.ixx>
|
|
|
|
#include <TopExp.hxx>
|
|
#include <TopExp_Explorer.hxx>
|
|
#include <TopoDS.hxx>
|
|
#include <TopoDS_Vertex.hxx>
|
|
#include <TopoDS_Wire.hxx>
|
|
#include <TopTools_ListOfShape.hxx>
|
|
#include <TopTools_ListIteratorOfListOfShape.hxx>
|
|
#include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
|
|
#include <Precision.hxx>
|
|
#include <BRep_Builder.hxx>
|
|
#include <BRep_ListIteratorOfListOfCurveRepresentation.hxx>
|
|
#include <BRep_TEdge.hxx>
|
|
#include <BRep_GCurve.hxx>
|
|
#include <BRep_Tool.hxx>
|
|
#include <gp_XYZ.hxx>
|
|
#include <gp_Pnt.hxx>
|
|
#include <TColgp_SequenceOfXYZ.hxx>
|
|
|
|
//#define POSITION_USES_MEAN_POINT
|
|
|
|
//=======================================================================
|
|
//function : ShapeFix_EdgeConnect
|
|
//=======================================================================
|
|
|
|
ShapeFix_EdgeConnect::ShapeFix_EdgeConnect () {}
|
|
|
|
//=======================================================================
|
|
//function : Add
|
|
//purpose : Adds connectivity information for two edges
|
|
//=======================================================================
|
|
|
|
void ShapeFix_EdgeConnect::Add (const TopoDS_Edge& aFirst, const TopoDS_Edge& aSecond)
|
|
{
|
|
// Select vertices to connect
|
|
TopoDS_Vertex theFirstVertex = TopExp::LastVertex( aFirst, Standard_True );
|
|
TopoDS_Vertex theSecondVertex = TopExp::FirstVertex( aSecond, Standard_True );
|
|
|
|
// Make necessary bindings
|
|
if ( myVertices.IsBound( theFirstVertex ) ) {
|
|
// First vertex is bound - find shared vertex
|
|
TopoDS_Vertex theFirstShared = TopoDS::Vertex( myVertices( theFirstVertex ) );
|
|
if ( myVertices.IsBound( theSecondVertex ) ) {
|
|
// Second vertex is bound - find shared vertex
|
|
TopoDS_Vertex theSecondShared = TopoDS::Vertex( myVertices( theSecondVertex ) );
|
|
if ( !theFirstShared.IsSame(theSecondShared) ) {
|
|
// Concatenate lists
|
|
TopTools_ListOfShape& theFirstList = myLists( theFirstShared );
|
|
TopTools_ListOfShape& theSecondList = myLists( theSecondShared );
|
|
for ( TopTools_ListIteratorOfListOfShape theIterator( theSecondList );
|
|
theIterator.More();
|
|
theIterator.Next() ) {
|
|
// Rebind shared vertex for current one
|
|
myVertices( theIterator.Value() ) = theFirstShared;
|
|
// Skip the following edge
|
|
theIterator.Next();
|
|
}
|
|
// Append second list to the first one
|
|
theFirstList.Append( theSecondList );
|
|
// Unbind the second shared vertex
|
|
myLists.UnBind( theSecondShared );
|
|
}
|
|
}
|
|
else {
|
|
// Bind second vertex with shared vertex of the first one
|
|
myVertices.Bind( theSecondVertex, theFirstShared );
|
|
// Add second vertex and second edge to the list
|
|
TopTools_ListOfShape& theFirstList = myLists( theFirstShared );
|
|
theFirstList.Append( theSecondVertex );
|
|
theFirstList.Append( aSecond );
|
|
}
|
|
}
|
|
else {
|
|
if ( myVertices.IsBound( theSecondVertex ) ) {
|
|
// Second vertex is bound - find shared vertex
|
|
TopoDS_Vertex& theSecondShared = TopoDS::Vertex( myVertices( theSecondVertex ) );
|
|
// Bind first vertex with shared vertex of the second one
|
|
myVertices.Bind( theFirstVertex, theSecondShared );
|
|
// Add first vertex and first edge to the list
|
|
TopTools_ListOfShape& theSecondList = myLists( theSecondShared );
|
|
theSecondList.Append( theFirstVertex );
|
|
theSecondList.Append( aFirst );
|
|
}
|
|
else {
|
|
// None is bound - create new bindings
|
|
myVertices.Bind( theFirstVertex, theFirstVertex );
|
|
myVertices.Bind( theSecondVertex, theFirstVertex );
|
|
TopTools_ListOfShape theNewList;
|
|
theNewList.Append( theFirstVertex );
|
|
theNewList.Append( aFirst );
|
|
theNewList.Append( theSecondVertex );
|
|
theNewList.Append( aSecond );
|
|
myLists.Bind( theFirstVertex, theNewList );
|
|
}
|
|
}
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : Add
|
|
//purpose : Adds connectivity information for the whole shape
|
|
//=======================================================================
|
|
|
|
void ShapeFix_EdgeConnect::Add (const TopoDS_Shape& aShape)
|
|
{
|
|
for ( TopExp_Explorer expw( aShape, TopAbs_WIRE ); expw.More(); expw.Next() ) {
|
|
TopoDS_Wire theWire = TopoDS::Wire(expw.Current());
|
|
TopExp_Explorer expe( theWire, TopAbs_EDGE );
|
|
if (expe.More()) {
|
|
// Obtain the first edge and remember it
|
|
TopoDS_Edge theEdge = TopoDS::Edge(expe.Current());
|
|
TopoDS_Edge theFirst = theEdge;
|
|
expe.Next();
|
|
for (; expe.More(); expe.Next()) {
|
|
// Obtain second edge and connect it
|
|
TopoDS_Edge theNext = TopoDS::Edge(expe.Current());
|
|
Add( theEdge, theNext );
|
|
theEdge = theNext;
|
|
}
|
|
// Connect first and last edges if wire is closed
|
|
if (theWire.Closed()) Add( theEdge, theFirst );
|
|
}
|
|
}
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : Build
|
|
//purpose : Builds shared vertices
|
|
//=======================================================================
|
|
|
|
void ShapeFix_EdgeConnect::Build ()
|
|
{
|
|
TopTools_ListIteratorOfListOfShape theLIterator;
|
|
BRep_ListIteratorOfListOfCurveRepresentation theCIterator;
|
|
|
|
TColgp_SequenceOfXYZ thePositions;
|
|
gp_XYZ thePosition;
|
|
Standard_Real theMaxDev;
|
|
BRep_Builder theBuilder;
|
|
|
|
// Iterate on shared vertices
|
|
for ( TopTools_DataMapIteratorOfDataMapOfShapeListOfShape theSIterator( myLists );
|
|
theSIterator.More();
|
|
theSIterator.Next() ) {
|
|
TopoDS_Vertex theSharedVertex = TopoDS::Vertex( theSIterator.Key() );
|
|
const TopTools_ListOfShape& theList = theSIterator.Value();
|
|
|
|
thePositions.Clear();
|
|
|
|
// Iterate on edges, accumulating positions
|
|
for ( theLIterator.Initialize( theList );
|
|
theLIterator.More();
|
|
theLIterator.Next() ) {
|
|
TopoDS_Vertex& theVertex = TopoDS::Vertex( theLIterator.Value() );
|
|
theLIterator.Next();
|
|
TopoDS_Edge& theEdge = TopoDS::Edge( theLIterator.Value() );
|
|
|
|
// Determine usage of curve bound points
|
|
TopoDS_Vertex theStart, theEnd;
|
|
theEdge.Orientation(TopAbs_FORWARD);
|
|
TopExp::Vertices( theEdge, theStart, theEnd );
|
|
Standard_Boolean use_start = ( theVertex.IsSame( theStart ) );
|
|
Standard_Boolean use_end = ( theVertex.IsSame( theEnd ) );
|
|
|
|
// Iterate on edge curves, accumulating positions
|
|
for (theCIterator.Initialize((*((Handle(BRep_TEdge)*)&theEdge.TShape()))->ChangeCurves());
|
|
theCIterator.More(); theCIterator.Next()) {
|
|
Handle(BRep_GCurve) GC = Handle(BRep_GCurve)::DownCast(theCIterator.Value());
|
|
if ( GC.IsNull() ) continue;
|
|
// Calculate vertex position for this curve
|
|
Standard_Real theFParam, theLParam;
|
|
GC->Range( theFParam, theLParam );
|
|
gp_Pnt thePoint;
|
|
if (use_start) {
|
|
GC->D0( theFParam, thePoint );
|
|
thePositions.Append( thePoint.XYZ() );
|
|
}
|
|
if (use_end) {
|
|
GC->D0( theLParam, thePoint );
|
|
thePositions.Append( thePoint.XYZ() );
|
|
}
|
|
}
|
|
}
|
|
|
|
Standard_Integer i, theNbPos = thePositions.Length();
|
|
|
|
// Calculate vertex position
|
|
thePosition = gp_XYZ(0.,0.,0.);
|
|
|
|
#ifdef POSITION_USES_MEAN_POINT
|
|
#undef POSITION_USES_MEAN_POINT
|
|
for ( i = 1; i <= theNbPos; i++ ) thePosition += thePositions.Value(i);
|
|
if ( theNbPos > 1 ) thePosition /= theNbPos;
|
|
#else
|
|
gp_XYZ theLBound(0.,0.,0.), theRBound(0.,0.,0.);
|
|
for ( i = 1; i <= theNbPos; i++ ) {
|
|
thePosition = thePositions.Value(i);
|
|
if ( i == 1 ) theLBound = theRBound = thePosition;
|
|
Standard_Real val = thePosition.X();
|
|
if ( val < theLBound.X() ) theLBound.SetX( val );
|
|
else if ( val > theRBound.X() ) theRBound.SetX( val );
|
|
val = thePosition.Y();
|
|
if ( val < theLBound.Y() ) theLBound.SetY( val );
|
|
else if ( val > theRBound.Y() ) theRBound.SetY( val );
|
|
val = thePosition.Z();
|
|
if ( val < theLBound.Z() ) theLBound.SetZ( val );
|
|
else if ( val > theRBound.Z() ) theRBound.SetZ( val );
|
|
}
|
|
if ( theNbPos > 1 ) thePosition = (theLBound + theRBound)/2.;
|
|
#endif
|
|
|
|
// Calculate maximal deviation
|
|
theMaxDev = 0.;
|
|
|
|
for ( i = 1; i <= theNbPos; i++ ) {
|
|
Standard_Real theDeviation = (thePosition-thePositions.Value(i)).Modulus();
|
|
if ( theDeviation > theMaxDev ) theMaxDev = theDeviation;
|
|
}
|
|
theMaxDev *= 1.0001; // To avoid numerical roundings
|
|
if ( theMaxDev < Precision::Confusion() ) theMaxDev = Precision::Confusion();
|
|
|
|
// Update shared vertex
|
|
theBuilder.UpdateVertex( theSharedVertex, gp_Pnt(thePosition), theMaxDev );
|
|
|
|
// Iterate on edges, adding shared vertex
|
|
for ( theLIterator.Initialize( theList );
|
|
theLIterator.More();
|
|
theLIterator.Next() ) {
|
|
TopoDS_Vertex& theVertex = TopoDS::Vertex( theLIterator.Value() );
|
|
theLIterator.Next();
|
|
TopoDS_Edge& theEdge = TopoDS::Edge( theLIterator.Value() );
|
|
|
|
// Determine usage of old vertices
|
|
TopoDS_Vertex theStart, theEnd;
|
|
theEdge.Orientation(TopAbs_FORWARD);
|
|
TopExp::Vertices( theEdge, theStart, theEnd );
|
|
Standard_Boolean use_start = ( theVertex.IsSame( theStart ) );
|
|
Standard_Boolean use_end = ( theVertex.IsSame( theEnd ) );
|
|
|
|
// Prepare vertex to remove
|
|
TopoDS_Vertex theOldVertex;
|
|
if (use_start) theOldVertex = theStart; // start is preferred for closed edges
|
|
else theOldVertex = theEnd;
|
|
|
|
// Prepare vertex to add
|
|
TopoDS_Vertex theNewVertex;
|
|
//smh#8 Porting AIX
|
|
if (use_start) {
|
|
TopoDS_Shape tmpshapeFwd = theSharedVertex.Oriented(TopAbs_FORWARD);
|
|
theNewVertex = TopoDS::Vertex(tmpshapeFwd);
|
|
}
|
|
else {
|
|
TopoDS_Shape tmpshapeRev = theSharedVertex.Oriented(TopAbs_REVERSED);
|
|
theNewVertex = TopoDS::Vertex(tmpshapeRev);
|
|
}
|
|
if ( !theOldVertex.IsSame(theNewVertex) ) {
|
|
// Replace vertices
|
|
Standard_Boolean freeflag = theEdge.Free();
|
|
theEdge.Free(Standard_True); //smh
|
|
theBuilder.Remove( theEdge, theOldVertex );
|
|
theBuilder.Add( theEdge, theNewVertex );
|
|
if (use_start && use_end) {
|
|
// process special case for closed edge
|
|
theBuilder.Remove( theEdge, theOldVertex.Oriented(TopAbs_REVERSED) ); // remove reversed from closed edge
|
|
theBuilder.Add( theEdge, theNewVertex.Oriented(TopAbs_REVERSED) ); // add reversed to closed edge
|
|
}
|
|
theEdge.Free(freeflag);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Clear maps after build
|
|
Clear();
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : Clear
|
|
//purpose :
|
|
//=======================================================================
|
|
|
|
void ShapeFix_EdgeConnect::Clear ()
|
|
{
|
|
myVertices.Clear();
|
|
myLists.Clear();
|
|
}
|