mirror of
https://github.com/Open-Cascade-SAS/OCCT.git
synced 2026-05-12 02:40:22 +08:00
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.
625 lines
17 KiB
C++
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;
|
|
}
|