Loading files
// Copyright (c) 1999-2014 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
//: q0 abv 12.03.99: mat-a.stp: protection against no pcurves in SwapSeam()
// abv 28.04.99 S4137: added method Add(WireData), method SetLast fixed
// abv 05.05.99 S4174: protection against INTERNAL/EXTERNAL edges
#include <BRep_Builder.hxx>
#include <BRep_Tool.hxx>
#include <BRepBuilderAPI_MakeWire.hxx>
#include <BRepTools_WireExplorer.hxx>
#include <Geom2d_Curve.hxx>
#include <ShapeExtend_WireData.hxx>
#include <Standard_Type.hxx>
#include <TopExp.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Edge.hxx>
#include <TopoDS_Face.hxx>
#include <TopoDS_Iterator.hxx>
#include <TopoDS_Shape.hxx>
#include <TopoDS_Vertex.hxx>
#include <TopoDS_Wire.hxx>
#include <TopTools_ShapeMapHasher.hxx>
#include <NCollection_IndexedMap.hxx>
IMPLEMENT_STANDARD_RTTIEXT(ShapeExtend_WireData, Standard_Transient)
//=================================================================================================
ShapeExtend_WireData::ShapeExtend_WireData()
{
Clear();
}
//=================================================================================================
ShapeExtend_WireData::ShapeExtend_WireData(const TopoDS_Wire& wire,
const bool chained,
const bool theManifold)
{
Init(wire, chained, theManifold);
}
//=================================================================================================
void ShapeExtend_WireData::Init(const occ::handle<ShapeExtend_WireData>& other)
{
Clear();
int i, nb = other->NbEdges();
for (i = 1; i <= nb; i++)
{
Add(other->Edge(i));
}
nb = other->NbNonManifoldEdges();
for (i = 1; i <= nb; i++)
{
Add(other->NonmanifoldEdge(i));
}
myManifoldMode = other->ManifoldMode();
}
//=================================================================================================
bool ShapeExtend_WireData::Init(const TopoDS_Wire& wire, const bool chained, const bool theManifold)
{
Clear();
myManifoldMode = theManifold;
bool OK = true;
TopoDS_Vertex Vlast;
for (TopoDS_Iterator it(wire); it.More(); it.Next())
{
TopoDS_Edge E = TopoDS::Edge(it.Value());
// protect against INTERNAL/EXTERNAL edges
if ((E.Orientation() != TopAbs_REVERSED && E.Orientation() != TopAbs_FORWARD))
{
myNonmanifoldEdges->Append(E);
continue;
}
TopoDS_Vertex V1, V2;
for (TopoDS_Iterator itv(E); itv.More(); itv.Next())
{
TopoDS_Vertex V = TopoDS::Vertex(itv.Value());
if (V.Orientation() == TopAbs_FORWARD)
{
V1 = V;
}
else if (V.Orientation() == TopAbs_REVERSED)
{
V2 = V;
}
}
// chainage? Si pas bon et chained False on repart sur WireExplorer
if (!Vlast.IsNull() && !Vlast.IsSame(V1) && theManifold)
{
OK = false;
if (!chained)
{
break;
}
}
Vlast = V2;
if (wire.Orientation() == TopAbs_REVERSED)
{
myEdges->Prepend(E);
}
else
{
myEdges->Append(E);
}
}
if (!myManifoldMode)
{
int nb = myNonmanifoldEdges->Length();
int i = 1;
for (; i <= nb; i++)
{
myEdges->Append(myNonmanifoldEdges->Value(i));
}
myNonmanifoldEdges->Clear();
}
// refaire chainage ? Par WireExplorer
if (OK || chained)
{
return OK;
}
Clear();
for (BRepTools_WireExplorer we(wire); we.More(); we.Next())
{
myEdges->Append(TopoDS::Edge(we.Current()));
}
return OK;
}
//=================================================================================================
void ShapeExtend_WireData::Clear()
{
myEdges = new NCollection_HSequence<TopoDS_Shape>();
myNonmanifoldEdges = new NCollection_HSequence<TopoDS_Shape>;
mySeamF = mySeamR = -1;
mySeams.Nullify();
myManifoldMode = true;
}
//=================================================================================================
void ShapeExtend_WireData::ComputeSeams(const bool enforce)
{
if (mySeamF >= 0 && !enforce)
{
return;
}
mySeams = new NCollection_HSequence<int>();
mySeamF = mySeamR = 0;
TopoDS_Shape S;
int i, nb = NbEdges();
NCollection_IndexedMap<TopoDS_Shape, TopTools_ShapeMapHasher> ME;
int* SE = new int[nb + 1];
// deux passes : d abord on mappe les Edges REVERSED
// Pour chacune, on note aussi son RANG dans la liste
for (i = 1; i <= nb; i++)
{
S = Edge(i);
if (S.Orientation() == TopAbs_REVERSED)
{
int num = ME.Add(S);
SE[num] = i;
}
}
// ensuite on voit les Edges FORWARD qui y seraient deja -> on note leur n0
// c-a-d le n0 de la directe ET de la reverse
for (i = 1; i <= nb; i++)
{
S = Edge(i);
if (S.Orientation() == TopAbs_REVERSED)
{
continue;
}
int num = ME.FindIndex(S);
if (num <= 0)
{
continue;
}
if (mySeamF == 0)
{
mySeamF = i;
mySeamR = SE[num];
}
else
{
mySeams->Append(i);
mySeams->Append(SE[num]);
}
}
mySeamsCache.Clear();
for (i = 1; i <= mySeams->Length(); i++)
{
mySeamsCache.Add(mySeams->Value(i));
}
delete[] SE; // ne pas oublier !!
}
//=================================================================================================
void ShapeExtend_WireData::SetLast(const int num)
{
if (num == 0)
{
return;
}
int i, nb = NbEdges();
for (i = nb; i > num; i--)
{
TopoDS_Edge edge = TopoDS::Edge(myEdges->Value(nb));
myEdges->Remove(nb);
myEdges->InsertBefore(1, edge);
}
mySeamF = -1;
}
//=================================================================================================
void ShapeExtend_WireData::SetDegeneratedLast()
{
int i, nb = NbEdges();
for (i = 1; i <= nb; i++)
{
if (BRep_Tool::Degenerated(Edge(i)))
{
SetLast(i);
return;
}
}
}
//=================================================================================================
void ShapeExtend_WireData::Add(const TopoDS_Edge& edge, const int atnum)
{
if (edge.Orientation() != TopAbs_REVERSED && edge.Orientation() != TopAbs_FORWARD
&& myManifoldMode)
{
myNonmanifoldEdges->Append(edge);
return;
}
if (edge.IsNull())
{
return;
}
if (atnum == 0)
{
myEdges->Append(edge);
}
else
{
myEdges->InsertBefore(atnum, edge);
}
mySeamF = -1;
}
//=================================================================================================
void ShapeExtend_WireData::Add(const TopoDS_Wire& wire, const int atnum)
{
if (wire.IsNull())
{
return;
}
int n = atnum;
NCollection_Sequence<TopoDS_Shape> aNMEdges;
for (TopoDS_Iterator it(wire); it.More(); it.Next())
{
TopoDS_Edge edge = TopoDS::Edge(it.Value());
if (edge.Orientation() != TopAbs_REVERSED && edge.Orientation() != TopAbs_FORWARD)
{
if (myManifoldMode)
{
myNonmanifoldEdges->Append(edge);
}
else
{
aNMEdges.Append(edge);
}
continue;
}
if (n == 0)
{
myEdges->Append(edge);
}
else
{
myEdges->InsertBefore(n, edge);
n++;
}
}
int i = 1, nb = aNMEdges.Length();
for (; i <= nb; i++)
{
myEdges->Append(aNMEdges.Value(i));
}
mySeamF = -1;
}
//=================================================================================================
void ShapeExtend_WireData::Add(const occ::handle<ShapeExtend_WireData>& wire, const int atnum)
{
if (wire.IsNull())
{
return;
}
NCollection_Sequence<TopoDS_Shape> aNMEdges;
int n = atnum;
int i = 1;
for (; i <= wire->NbEdges(); i++)
{
TopoDS_Edge aE = wire->Edge(i);
if (aE.Orientation() == TopAbs_INTERNAL || aE.Orientation() == TopAbs_EXTERNAL)
{
aNMEdges.Append(aE);
continue;
}
if (n == 0)
{
myEdges->Append(wire->Edge(i));
}
else
{
myEdges->InsertBefore(n, wire->Edge(i));
n++;
}
}
// non-manifold edges for non-manifold wire should be added at end
for (i = 1; i <= aNMEdges.Length(); i++)
{
myEdges->Append(aNMEdges.Value(i));
}
for (i = 1; i <= wire->NbNonManifoldEdges(); i++)
{
if (myManifoldMode)
{
myNonmanifoldEdges->Append(wire->NonmanifoldEdge(i));
}
else
{
if (n == 0)
{
myEdges->Append(wire->Edge(i));
}
else
{
myEdges->InsertBefore(n, wire->Edge(i));
n++;
}
}
}
mySeamF = -1;
}
//=================================================================================================
void ShapeExtend_WireData::Add(const TopoDS_Shape& shape, const int atnum)
{
if (shape.ShapeType() == TopAbs_EDGE)
{
Add(TopoDS::Edge(shape), atnum);
}
else if (shape.ShapeType() == TopAbs_WIRE)
{
Add(TopoDS::Wire(shape), atnum);
}
}
//=================================================================================================
void ShapeExtend_WireData::AddOriented(const TopoDS_Edge& edge, const int mode)
{
if (edge.IsNull() || mode < 0)
{
return;
}
TopoDS_Edge E = edge;
if (mode == 1 || mode == 3)
{
E.Reverse();
}
Add(E, mode / 2); // mode = 0,1 -> 0 mode = 2,3 -> 1
}
//=================================================================================================
void ShapeExtend_WireData::AddOriented(const TopoDS_Wire& wire, const int mode)
{
if (wire.IsNull() || mode < 0)
{
return;
}
TopoDS_Wire W = wire;
if (mode == 1 || mode == 3)
{
W.Reverse();
}
Add(W, mode / 2); // mode = 0,1 -> 0 mode = 2,3 -> 1
}
void ShapeExtend_WireData::AddOriented(const TopoDS_Shape& shape, const int mode)
{
if (shape.ShapeType() == TopAbs_EDGE)
{
AddOriented(TopoDS::Edge(shape), mode);
}
else if (shape.ShapeType() == TopAbs_WIRE)
{
AddOriented(TopoDS::Wire(shape), mode);
}
}
//=================================================================================================
void ShapeExtend_WireData::Remove(const int num)
{
myEdges->Remove(num > 0 ? num : NbEdges());
mySeamF = -1;
}
//=================================================================================================
void ShapeExtend_WireData::Set(const TopoDS_Edge& edge, const int num)
{
if (edge.Orientation() != TopAbs_REVERSED && edge.Orientation() != TopAbs_FORWARD
&& myManifoldMode)
{
if (num <= myNonmanifoldEdges->Length())
{
myNonmanifoldEdges->SetValue(num, edge);
}
else
{
myNonmanifoldEdges->Append(edge);
}
}
else
{
myEdges->SetValue((num > 0 ? num : NbEdges()), edge);
}
mySeamF = -1;
}
//=======================================================================
// function : Reverse
// purpose : reverse order of edges in the wire
//=======================================================================
void ShapeExtend_WireData::Reverse()
{
int i, nb = NbEdges();
// inverser les edges + les permuter pour inverser le wire
for (i = 1; i <= nb / 2; i++)
{
TopoDS_Shape S1 = myEdges->Value(i);
S1.Reverse();
TopoDS_Shape S2 = myEdges->Value(nb + 1 - i);
S2.Reverse();
myEdges->SetValue(i, S2);
myEdges->SetValue(nb + 1 - i, S1);
}
// nb d edges impair : inverser aussi l edge du milieu (rang inchange)
if (nb % 2)
{ // test impair
i = (nb + 1) / 2;
TopoDS_Shape SI = myEdges->Value(i);
SI.Reverse();
myEdges->SetValue(i, SI);
}
mySeamF = -1;
}
//=================================================================================================
// Fonction auxiliaire SwapSeam pour inverser
static void SwapSeam(const TopoDS_Shape& S, const TopoDS_Face& F)
{
TopoDS_Edge E = TopoDS::Edge(S);
if (E.IsNull() || F.IsNull())
{
return;
}
if (E.Orientation() == TopAbs_REVERSED)
{
return; // ne le faire qu une fois !
}
TopoDS_Face theface = F;
theface.Orientation(TopAbs_FORWARD);
//: S4136 double Tol = BRep_Tool::Tolerance(theface);
occ::handle<Geom2d_Curve> c2df, c2dr;
double uff, ulf, ufr, ulr;
// d abord FWD puis REV
c2df = BRep_Tool::CurveOnSurface(E, theface, uff, ulf);
E.Orientation(TopAbs_REVERSED);
c2dr = BRep_Tool::CurveOnSurface(E, theface, ufr, ulr);
if (c2df.IsNull() || c2dr.IsNull())
{
return; //: q0
}
// On permute
E.Orientation(TopAbs_FORWARD);
BRep_Builder B;
B.UpdateEdge(E, c2dr, c2df, theface, 0.); //: S4136: Tol
B.Range(E, theface, uff, ulf);
}
void ShapeExtend_WireData::Reverse(const TopoDS_Face& face)
{
Reverse();
if (face.IsNull())
{
return;
}
// ATTENTION aux coutures
// Une edge de couture est presente deux fois, FWD et REV
// Les inverser revient a permuter leur role ... donc ne rien faire
// Il faut donc aussi permuter leurs pcurves
ComputeSeams(true);
if (mySeamF > 0)
{
SwapSeam(myEdges->Value(mySeamF), face);
}
if (mySeamR > 0)
{
SwapSeam(myEdges->Value(mySeamR), face);
}
int nb = (mySeams.IsNull() ? 0 : mySeams->Length());
for (int i = 1; i <= nb; i++)
{
SwapSeam(myEdges->Value(mySeams->Value(i)), face);
}
mySeamF = -1;
}
//=================================================================================================
int ShapeExtend_WireData::NbEdges() const
{
return myEdges->Length();
}
//=================================================================================================
TopoDS_Edge ShapeExtend_WireData::Edge(const int num) const
{
if (num < 0)
{
TopoDS_Edge E = Edge(-num);
E.Reverse();
return E;
}
return TopoDS::Edge(myEdges->Value(num));
}
//=================================================================================================
int ShapeExtend_WireData::NbNonManifoldEdges() const
{
return myNonmanifoldEdges->Length();
}
//=================================================================================================
TopoDS_Edge ShapeExtend_WireData::NonmanifoldEdge(const int num) const
{
TopoDS_Edge E;
if (num < 0)
{
return E;
}
return TopoDS::Edge(myNonmanifoldEdges->Value(num));
}
//=================================================================================================
int ShapeExtend_WireData::Index(const TopoDS_Edge& edge)
{
for (int i = 1; i <= NbEdges(); i++)
{
if (Edge(i).IsSame(edge) && (Edge(i).Orientation() == edge.Orientation() || !IsSeam(i)))
{
return i;
}
}
return 0;
}
//=================================================================================================
bool ShapeExtend_WireData::IsSeam(const int num)
{
if (mySeamF < 0)
{
ComputeSeams();
}
if (mySeamF == 0)
{
return false;
}
if (num == mySeamF || num == mySeamR)
{
return true;
}
// Use hash set for O(1) lookup instead of O(n) linear search
return mySeamsCache.Contains(num);
}
//=================================================================================================
TopoDS_Wire ShapeExtend_WireData::Wire() const
{
TopoDS_Wire W;
BRep_Builder B;
B.MakeWire(W);
int i, nb = NbEdges();
bool ismanifold = true;
for (i = 1; i <= nb; i++)
{
TopoDS_Edge aE = Edge(i);
if (aE.Orientation() != TopAbs_FORWARD && aE.Orientation() != TopAbs_REVERSED)
{
ismanifold = false;
}
B.Add(W, aE);
}
if (ismanifold)
{
TopoDS_Vertex vf, vl;
TopExp::Vertices(W, vf, vl);
if (!vf.IsNull() && !vl.IsNull() && vf.IsSame(vl))
{
W.Closed(true);
}
}
if (myManifoldMode)
{
nb = NbNonManifoldEdges();
for (i = 1; i <= nb; i++)
{
B.Add(W, NonmanifoldEdge(i));
}
}
return W;
}
//=================================================================================================
TopoDS_Wire ShapeExtend_WireData::WireAPIMake() const
{
TopoDS_Wire W;
BRepBuilderAPI_MakeWire MW;
int i, nb = NbEdges();
for (i = 1; i <= nb; i++)
{
MW.Add(Edge(i));
}
if (myManifoldMode)
{
nb = NbNonManifoldEdges();
for (i = 1; i <= nb; i++)
{
MW.Add(NonmanifoldEdge(i));
}
}
if (MW.IsDone())
{
W = MW.Wire();
}
return W;
}
//=================================================================================================
occ::handle<NCollection_HSequence<TopoDS_Shape>> ShapeExtend_WireData::NonmanifoldEdges() const
{
return myNonmanifoldEdges;
}
//=================================================================================================
bool& ShapeExtend_WireData::ManifoldMode()
{
return myManifoldMode;
}
f2929057eThis file is pinned to the selected release. Download the original to open it in your design tool.