Files
OCCT/src/ModelingAlgorithms/TKShHealing/ShapeExtend/ShapeExtend_WireData.cxx
Pasukhin Dmitry 5647b46a34 Configuration - Reorganize repository structure #450
Reorganizing structure to have Module/TK/Package/FILES structure.
New structure reflect the structure inside IDE.
Migrate FILES, PACKAGES, EXTRLIB to CMake version to handle changes on updates.
No changes were done to installation layout, all installation result keep as before.
The migration was done using python script, see PR, which refactor automatically the structure.
Updated doc generation to have valid path to modules, toolkits and packages.
In case of PR into new version, IR-790 can be used as a target for the previous version.
2025-03-20 00:39:26 +00:00

625 lines
17 KiB
C++

// 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_IndexedMapOfShape.hxx>
IMPLEMENT_STANDARD_RTTIEXT(ShapeExtend_WireData, Standard_Transient)
//=================================================================================================
ShapeExtend_WireData::ShapeExtend_WireData()
{
Clear();
}
//=================================================================================================
ShapeExtend_WireData::ShapeExtend_WireData(const TopoDS_Wire& wire,
const Standard_Boolean chained,
const Standard_Boolean theManifold)
{
Init(wire, chained, theManifold);
}
//=================================================================================================
void ShapeExtend_WireData::Init(const Handle(ShapeExtend_WireData)& other)
{
Clear();
Standard_Integer 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();
}
//=================================================================================================
Standard_Boolean ShapeExtend_WireData::Init(const TopoDS_Wire& wire,
const Standard_Boolean chained,
const Standard_Boolean theManifold)
{
Clear();
myManifoldMode = theManifold;
Standard_Boolean OK = Standard_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 = Standard_False;
if (!chained)
break;
}
Vlast = V2;
if (wire.Orientation() == TopAbs_REVERSED)
myEdges->Prepend(E);
else
myEdges->Append(E);
}
if (!myManifoldMode)
{
Standard_Integer nb = myNonmanifoldEdges->Length();
Standard_Integer 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 TopTools_HSequenceOfShape();
myNonmanifoldEdges = new TopTools_HSequenceOfShape;
mySeamF = mySeamR = -1;
mySeams.Nullify();
myManifoldMode = Standard_True;
}
//=================================================================================================
void ShapeExtend_WireData::ComputeSeams(const Standard_Boolean enforce)
{
if (mySeamF >= 0 && !enforce)
return;
mySeams = new TColStd_HSequenceOfInteger();
mySeamF = mySeamR = 0;
TopoDS_Shape S;
Standard_Integer i, nb = NbEdges();
TopTools_IndexedMapOfShape ME;
Standard_Integer* SE = new Standard_Integer[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)
{
Standard_Integer 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;
Standard_Integer num = ME.FindIndex(S);
if (num <= 0)
continue;
if (mySeamF == 0)
{
mySeamF = i;
mySeamR = SE[num];
}
else
{
mySeams->Append(i);
mySeams->Append(SE[num]);
}
}
delete[] SE; // ne pas oublier !!
}
//=================================================================================================
void ShapeExtend_WireData::SetLast(const Standard_Integer num)
{
if (num == 0)
return;
Standard_Integer 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()
{
Standard_Integer 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 Standard_Integer 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 Standard_Integer atnum)
{
if (wire.IsNull())
return;
Standard_Integer n = atnum;
TopTools_SequenceOfShape 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++;
}
}
Standard_Integer i = 1, nb = aNMEdges.Length();
for (; i <= nb; i++)
myEdges->Append(aNMEdges.Value(i));
mySeamF = -1;
}
//=================================================================================================
void ShapeExtend_WireData::Add(const Handle(ShapeExtend_WireData)& wire,
const Standard_Integer atnum)
{
if (wire.IsNull())
return;
TopTools_SequenceOfShape aNMEdges;
Standard_Integer n = atnum;
Standard_Integer 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 Standard_Integer 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 Standard_Integer 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 Standard_Integer 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 Standard_Integer 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 Standard_Integer num)
{
myEdges->Remove(num > 0 ? num : NbEdges());
mySeamF = -1;
}
//=================================================================================================
void ShapeExtend_WireData::Set(const TopoDS_Edge& edge, const Standard_Integer 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()
{
Standard_Integer 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 Standard_Real Tol = BRep_Tool::Tolerance(theface);
Handle(Geom2d_Curve) c2df, c2dr;
Standard_Real 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(Standard_True);
if (mySeamF > 0)
SwapSeam(myEdges->Value(mySeamF), face);
if (mySeamR > 0)
SwapSeam(myEdges->Value(mySeamR), face);
Standard_Integer nb = (mySeams.IsNull() ? 0 : mySeams->Length());
for (Standard_Integer i = 1; i <= nb; i++)
{
SwapSeam(myEdges->Value(mySeams->Value(i)), face);
}
mySeamF = -1;
}
//=================================================================================================
Standard_Integer ShapeExtend_WireData::NbEdges() const
{
return myEdges->Length();
}
//=================================================================================================
TopoDS_Edge ShapeExtend_WireData::Edge(const Standard_Integer num) const
{
if (num < 0)
{
TopoDS_Edge E = Edge(-num);
E.Reverse();
return E;
}
return TopoDS::Edge(myEdges->Value(num));
}
//=================================================================================================
Standard_Integer ShapeExtend_WireData::NbNonManifoldEdges() const
{
return myNonmanifoldEdges->Length();
}
//=================================================================================================
TopoDS_Edge ShapeExtend_WireData::NonmanifoldEdge(const Standard_Integer num) const
{
TopoDS_Edge E;
if (num < 0)
return E;
return TopoDS::Edge(myNonmanifoldEdges->Value(num));
}
//=================================================================================================
Standard_Integer ShapeExtend_WireData::Index(const TopoDS_Edge& edge)
{
for (Standard_Integer i = 1; i <= NbEdges(); i++)
if (Edge(i).IsSame(edge) && (Edge(i).Orientation() == edge.Orientation() || !IsSeam(i)))
return i;
return 0;
}
//=================================================================================================
Standard_Boolean ShapeExtend_WireData::IsSeam(const Standard_Integer num)
{
if (mySeamF < 0)
ComputeSeams();
if (mySeamF == 0)
return Standard_False;
if (num == mySeamF || num == mySeamR)
return Standard_True;
// Pas suffisant : on regarde dans la liste
Standard_Integer i, nb = mySeams->Length();
for (i = 1; i <= nb; i++)
{
if (num == mySeams->Value(i))
return Standard_True;
}
return Standard_False;
}
//=================================================================================================
TopoDS_Wire ShapeExtend_WireData::Wire() const
{
TopoDS_Wire W;
BRep_Builder B;
B.MakeWire(W);
Standard_Integer i, nb = NbEdges();
Standard_Boolean ismanifold = Standard_True;
for (i = 1; i <= nb; i++)
{
TopoDS_Edge aE = Edge(i);
if (aE.Orientation() != TopAbs_FORWARD && aE.Orientation() != TopAbs_REVERSED)
ismanifold = Standard_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(Standard_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;
Standard_Integer 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;
}
//=================================================================================================
Handle(TopTools_HSequenceOfShape) ShapeExtend_WireData::NonmanifoldEdges() const
{
return myNonmanifoldEdges;
}
//=================================================================================================
Standard_Boolean& ShapeExtend_WireData::ManifoldMode()
{
return myManifoldMode;
}