1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-08-14 13:30:48 +03:00

Integration of OCCT 6.5.0 from SVN

This commit is contained in:
bugmaster
2011-03-16 07:30:28 +00:00
committed by bugmaster
parent 4903637061
commit 7fd59977df
16375 changed files with 3882564 additions and 0 deletions

14
src/Poly/FILES Executable file
View File

@@ -0,0 +1,14 @@
Handle_Poly_CoherentTriangulation.hxx
Poly_CoherentTriangulation.hxx
Poly_CoherentTriangle.hxx
Poly_CoherentTriPtr.hxx
Poly_CoherentNode.hxx
Poly_CoherentLink.hxx
Poly_CoherentTriangulation.cxx
Poly_CoherentTriangle.cxx
Poly_CoherentTriPtr.cxx
Poly_CoherentNode.cxx
Poly_CoherentLink.cxx
Poly_MakeLoops.hxx
Poly_MakeLoops.cxx
Poly_ListOfTriangulation.hxx

View File

@@ -0,0 +1,18 @@
// File: Handle_Poly_CoherentTriangulation.hxx
// Created: 23.04.08 19:00
// Author: Alexander GRIGORIEV
// Copyright: Open Cascade 2008
#ifndef Handle_Poly_CoherentTriangulation_HeaderFile
#define Handle_Poly_CoherentTriangulation_HeaderFile
#include <Standard_DefineHandle.hxx>
#include <Standard_Transient.hxx>
class Poly_CoherentTriangulation;
//! Definition of HANDLE object using Standard_DefineHandle.hxx
DEFINE_STANDARD_HANDLE (Poly_CoherentTriangulation, Standard_Transient)
#endif

164
src/Poly/Poly.cdl Executable file
View File

@@ -0,0 +1,164 @@
-- -- File: Poly.cdl
-- Created: Mon Mar 6 09:38:50 1995
-- Author: Laurent PAINNOT
-- <lpa@metrox>
---Copyright: Matra Datavision 1995
package Poly
---Purpose: This package provides classes and services to
-- handle :
--
-- * 3D triangular polyhedrons.
--
-- * 3D polygons.
--
-- * 2D polygon.
--
-- * Tools to dump, save and restore those objects.
uses
MMgt,
TCollection,
TColStd,
gp,
TColgp,
TShort
is
class Triangle;
---Purpose: A triangle is a triplet of integers (indices of
-- the nodes).
class Array1OfTriangle
instantiates Array1 from TCollection(Triangle from Poly);
class HArray1OfTriangle
instantiates HArray1 from TCollection(Triangle from Poly,
Array1OfTriangle from Poly);
class Triangulation;
---Purpose: A Triangulation is a 3D polyhedron made of
-- triangles. It is made of a nodes which are
-- indexed. Nodes have a 3d value and a 2d value.
-- Triangles are triplet of node indices.
--
-- This is a Transient class.
class Polygon3D;
---Purpose: A Polygon3D is made of indexed nodes.
-- Nodes have a 3d value.
class Polygon2D;
---Purpose: A Polygon2D is made of indexed nodes.
-- Nodes have a 2d value.
class PolygonOnTriangulation;
---Purpose: A polygonOnTriangulation is made of node indices
-- referencing a triangulation.
--
-- Tools to use triangulations
--
class Connect;
---Purpose: Computes and stores the link from nodes to
-- triangles and from triangles to neighbouring
-- triangles.
-- This tool is obsolete, replaced by Poly_CoherentTriangulation
--
-- Data types for the Coherent Triangulation data model
--
imported CogerentTriangulation;
imported CoherentTriangle;
imported CoherentNode;
imported CoherentLink;
imported CoherentTriPtr;
imported ListOfTriangulation;
imported MakeLoops;
---Purpose: Algorithm to make minimal loops in a graph
--
-- Package methods
--
Catenate (lstTri: ListOfTriangulation from Poly)
returns Triangulation from Poly;
---Purpose: Join several triangulations to one new triangulation object.
-- The new triangulation is just a mechanical sum of input
-- triangulations, without node sharing. UV coordinates are
-- dropped in the result.
Write(T : Triangulation from Poly;
OS : in out OStream;
Compact : Boolean = Standard_True);
---Purpose: Writes the content of the triangulation <T> on the
-- stream <OS>. If <Compact> is true this is a "save"
-- format intended to be read back with the Read
-- method. If compact is False it is a "Dump" format
-- intended to be informative.
Write(P : Polygon3D from Poly;
OS : in out OStream;
Compact : Boolean = Standard_True);
---Purpose: Writes the content of the 3D polygon <P> on the
-- stream <OS>. If <Compact> is true this is a "save"
-- format intended to be read back with the Read
-- method. If compact is False it is a "Dump" format
-- intended to be informative.
Write(P : Polygon2D from Poly;
OS : in out OStream;
Compact : Boolean = Standard_True);
---Purpose: Writes the content of the 2D polygon <P> on the
-- stream <OS>. If <Compact> is true this is a "save"
-- format intended to be read back with the Read
-- method. If compact is False it is a "Dump" format
-- intended to be informative.
Dump(T : Triangulation from Poly;
OS : in out OStream);
---Purpose: Dumps the triangulation. This is a call to the
-- previous method with Comapct set to False.
Dump(P : Polygon3D from Poly;
OS : in out OStream);
---Purpose: Dumps the 3D polygon. This is a call to the
-- previous method with Comapct set to False.
Dump(P : Polygon2D from Poly;
OS : in out OStream);
---Purpose: Dumps the 2D polygon. This is a call to the
-- previous method with Comapct set to False.
ReadTriangulation(IS : in out IStream)
returns Triangulation from Poly;
---Purpose: Reads a triangulation from the stream <IS>.
ReadPolygon3D(IS : in out IStream)
returns Polygon3D from Poly;
---Purpose: Reads a 3d polygon from the stream <IS>.
ReadPolygon2D(IS : in out IStream)
returns Polygon2D from Poly;
---Purpose: Reads a 2D polygon from the stream <IS>.
ComputeNormals(Tri : Triangulation from Poly);
---Purpose: Compute node normals for face triangulation
-- as mean normal of surrounding triangles
end Poly;

495
src/Poly/Poly.cxx Executable file
View File

@@ -0,0 +1,495 @@
// File: Poly.cxx
// Created: Mon Mar 6 11:02:24 1995
// Author: Laurent PAINNOT
// <lpa@metrox>
#include <Standard_Stream.hxx>
#include <Poly.ixx>
#include <gp_Pnt.hxx>
#include <gp_Pnt2d.hxx>
#include <Poly_Triangle.hxx>
#include <TColgp_Array1OfPnt.hxx>
#include <TColgp_Array1OfPnt.hxx>
#include <TColStd_Array1OfReal.hxx>
#include <Poly_Array1OfTriangle.hxx>
#include <Poly_ListOfTriangulation.hxx>
#include <Poly_Polygon3D.hxx>
#include <Poly_Polygon2D.hxx>
#include <Precision.hxx>
#include <TShort_Array1OfShortReal.hxx>
#include <TShort_HArray1OfShortReal.hxx>
//=======================================================================
//function : Catenate
//purpose : Join several triangulations to one new triangulation object
//=======================================================================
Handle(Poly_Triangulation) Poly::Catenate
(const Poly_ListOfTriangulation& lstTri)
{
Standard_Integer nNodes(0);
Standard_Integer nTrian(0);
// Sum up the total number of nodes.
Poly_ListOfTriangulation::Iterator anIter(lstTri);
for (; anIter.More(); anIter.Next()) {
const Handle(Poly_Triangulation)& aTri = anIter.Value();
if (aTri.IsNull() == Standard_False) {
nNodes += aTri->NbNodes();
nTrian += aTri->NbTriangles();
}
}
Handle(Poly_Triangulation) aResult;
if (nNodes > 0) {
aResult = new Poly_Triangulation(nNodes, nTrian, Standard_False);
Standard_Integer i, iNode[3];
nNodes = 0;
nTrian = 0;
TColgp_Array1OfPnt& arrNode = aResult->ChangeNodes();
Poly_Array1OfTriangle& arrTrian = aResult->ChangeTriangles();
for (anIter.Init(lstTri); anIter.More(); anIter.Next()) {
const Handle(Poly_Triangulation)& aTri = anIter.Value();
if (aTri.IsNull() == Standard_False) {
const TColgp_Array1OfPnt& srcNode = aTri->Nodes();
const Poly_Array1OfTriangle& srcTrian = aTri->Triangles();
const Standard_Integer nbNodes = aTri->NbNodes();
const Standard_Integer nbTrian = aTri->NbTriangles();
for (i = 1; i <= nbNodes; i++) {
arrNode.SetValue(i + nNodes, srcNode(i));
}
for (i = 1; i <= nbTrian; i++) {
srcTrian(i).Get(iNode[0], iNode[1], iNode[2]);
arrTrian.SetValue(i + nTrian, Poly_Triangle(iNode[0] + nNodes,
iNode[1] + nNodes,
iNode[2] + nNodes));
}
nNodes += nbNodes;
nTrian += nbTrian;
}
}
}
return aResult;
}
//=======================================================================
//function : Write
//purpose :
//=======================================================================
void Poly::Write(const Handle(Poly_Triangulation)& T,
Standard_OStream& OS,
const Standard_Boolean Compact)
{
OS << "Poly_Triangulation\n";
if (Compact) {
OS << T->NbNodes() << " " << T->NbTriangles() << " ";
OS << ((T->HasUVNodes()) ? "1" : "0") << "\n";
}
else {
OS << setw(8) << T->NbNodes() << " Nodes\n";
OS << setw(8) << T->NbTriangles() << " Triangles\n";
OS << ((T->HasUVNodes()) ? "with" : "without") << " UV nodes\n";
}
// write the deflection
if (!Compact) OS << "Deflection : ";
OS << T->Deflection() << "\n";
// write the 3d nodes
if (!Compact) OS << "\n3D Nodes :\n";
Standard_Integer i, nbNodes = T->NbNodes();
const TColgp_Array1OfPnt& Nodes = T->Nodes();
for (i = 1; i <= nbNodes; i++) {
if (!Compact) OS << setw(10) << i << " : ";
if (!Compact) OS << setw(17);
OS << Nodes(i).X() << " ";
if (!Compact) OS << setw(17);
OS << Nodes(i).Y() << " ";
if (!Compact) OS << setw(17);
OS << Nodes(i).Z() << "\n";
}
if (T->HasUVNodes()) {
if (!Compact) OS << "\nUV Nodes :\n";
const TColgp_Array1OfPnt2d& UVNodes = T->UVNodes();
for (i = 1; i <= nbNodes; i++) {
if (!Compact) OS << setw(10) << i << " : ";
if (!Compact) OS << setw(17);
OS << UVNodes(i).X() << " ";
if (!Compact) OS << setw(17);
OS << UVNodes(i).Y() << "\n";
}
}
if (!Compact) OS << "\nTriangles :\n";
Standard_Integer nbTriangles = T->NbTriangles();
Standard_Integer n1, n2, n3;
const Poly_Array1OfTriangle& Triangles = T->Triangles();
for (i = 1; i <= nbTriangles; i++) {
if (!Compact) OS << setw(10) << i << " : ";
Triangles(i).Get(n1, n2, n3);
if (!Compact) OS << setw(10);
OS << n1 << " ";
if (!Compact) OS << setw(10);
OS << n2 << " ";
if (!Compact) OS << setw(10);
OS << n3 << "\n";
}
}
//=======================================================================
//function : Write
//purpose :
//=======================================================================
void Poly::Write(const Handle(Poly_Polygon3D)& P,
Standard_OStream& OS,
const Standard_Boolean Compact)
{
OS << "Poly_Polygon3D\n";
if (Compact) {
OS << P->NbNodes() << " ";
OS << ((P->HasParameters()) ? "1" : "0") << "\n";
}
else {
OS << setw(8) << P->NbNodes() << " Nodes\n";
OS << ((P->HasParameters()) ? "with" : "without") << " parameters\n";
}
// write the deflection
if (!Compact) OS << "Deflection : ";
OS << P->Deflection() << "\n";
// write the nodes
if (!Compact) OS << "\nNodes :\n";
Standard_Integer i, nbNodes = P->NbNodes();
const TColgp_Array1OfPnt& Nodes = P->Nodes();
for (i = 1; i <= nbNodes; i++) {
if (!Compact) OS << setw(10) << i << " : ";
if (!Compact) OS << setw(17);
OS << Nodes(i).X() << " ";
if (!Compact) OS << setw(17);
OS << Nodes(i).Y() << " ";
if (!Compact) OS << setw(17);
OS << Nodes(i).Z() << "\n";
}
if (P->HasParameters()) {
if (!Compact) OS << "\nParameters :\n";
const TColStd_Array1OfReal& Param = P->Parameters();
for (i = 1; i <= nbNodes; i++) {
OS << Param(i) << " ";
}
OS <<"\n";
}
}
//=======================================================================
//function : Write
//purpose :
//=======================================================================
void Poly::Write(const Handle(Poly_Polygon2D)& P,
Standard_OStream& OS,
const Standard_Boolean Compact)
{
OS << "Poly_Polygon2D\n";
if (Compact) {
OS << P->NbNodes() << " ";
}
else {
OS << setw(8) << P->NbNodes() << " Nodes\n";
}
// write the deflection
if (!Compact) OS << "Deflection : ";
OS << P->Deflection() << "\n";
// write the nodes
if (!Compact) OS << "\nNodes :\n";
Standard_Integer i, nbNodes = P->NbNodes();
const TColgp_Array1OfPnt2d& Nodes = P->Nodes();
for (i = 1; i <= nbNodes; i++) {
if (!Compact) OS << setw(10) << i << " : ";
if (!Compact) OS << setw(17);
OS << Nodes(i).X() << " ";
if (!Compact) OS << setw(17);
OS << Nodes(i).Y() << "\n";
}
}
//=======================================================================
//function : Dump
//purpose :
//=======================================================================
void Poly::Dump(const Handle(Poly_Triangulation)& T, Standard_OStream& OS)
{
Poly::Write(T,OS,Standard_False);
}
//=======================================================================
//function : Dump
//purpose :
//=======================================================================
void Poly::Dump(const Handle(Poly_Polygon3D)& P, Standard_OStream& OS)
{
Poly::Write(P,OS,Standard_False);
}
//=======================================================================
//function : Dump
//purpose :
//=======================================================================
void Poly::Dump(const Handle(Poly_Polygon2D)& P, Standard_OStream& OS)
{
Poly::Write(P,OS,Standard_False);
}
//=======================================================================
//function : ReadTriangulation
//purpose :
//=======================================================================
Handle(Poly_Triangulation) Poly::ReadTriangulation(Standard_IStream& IS)
{
// Read a triangulation
char line[100];
IS >> line;
if (strcmp(line,"Poly_Triangulation")) {
cout << "Not a Triangulation in the file" << endl;
return Handle(Poly_Triangulation)();
}
Standard_Integer nbNodes, nbTriangles;
Standard_Boolean hasUV;
IS >> nbNodes >> nbTriangles >> hasUV;
Standard_Real d;
IS >> d;
// read the 3d nodes
Standard_Real x,y,z;
Standard_Integer i;
TColgp_Array1OfPnt Nodes(1, nbNodes);
TColgp_Array1OfPnt2d UVNodes(1, nbNodes);
for (i = 1; i <= nbNodes; i++) {
IS >> x >> y >> z;
Nodes(i).SetCoord(x,y,z);
}
// read the UV points if necessary
if (hasUV) {
for (i = 1; i <= nbNodes; i++) {
IS >> x >> y;
UVNodes(i).SetCoord(x,y);
}
}
// read the triangles
Standard_Integer n1,n2,n3;
Poly_Array1OfTriangle Triangles(1, nbTriangles);
for (i = 1; i <= nbTriangles; i++) {
IS >> n1 >> n2 >> n3;
Triangles(i).Set(n1,n2,n3);
}
Handle(Poly_Triangulation) T;
if (hasUV) T = new Poly_Triangulation(Nodes,UVNodes,Triangles);
else T = new Poly_Triangulation(Nodes,Triangles);
T->Deflection(d);
return T;
}
//=======================================================================
//function : ReadPolygon3D
//purpose :
//=======================================================================
Handle(Poly_Polygon3D) Poly::ReadPolygon3D(Standard_IStream& IS)
{
// Read a 3d polygon
char line[100];
IS >> line;
if (strcmp(line,"Poly_Polygon3D")) {
cout << "Not a Polygon3D in the file" << endl;
return Handle(Poly_Polygon3D)();
}
Standard_Integer nbNodes;
IS >> nbNodes;
Standard_Boolean hasparameters;
IS >> hasparameters;
Standard_Real d;
IS >> d;
// read the nodes
Standard_Real x,y,z;
Standard_Integer i;
TColgp_Array1OfPnt Nodes(1, nbNodes);
for (i = 1; i <= nbNodes; i++) {
IS >> x >> y >> z;
Nodes(i).SetCoord(x,y,z);
}
TColStd_Array1OfReal Param(1,nbNodes);
if (hasparameters) {
for (i = 1; i <= nbNodes; i++) {
IS >> Param(i);
}
}
Handle(Poly_Polygon3D) P;
if (!hasparameters)
P = new Poly_Polygon3D(Nodes);
else
P = new Poly_Polygon3D(Nodes, Param);
P->Deflection(d);
return P;
}
//=======================================================================
//function : ReadPolygon3D
//purpose :
//=======================================================================
Handle(Poly_Polygon2D) Poly::ReadPolygon2D(Standard_IStream& IS)
{
// Read a 2d polygon
char line[100];
IS >> line;
if (strcmp(line,"Poly_Polygon2D")) {
cout << "Not a Polygon2D in the file" << endl;
return Handle(Poly_Polygon2D)();
}
Standard_Integer nbNodes;
IS >> nbNodes;
Standard_Real d;
IS >> d;
// read the nodes
Standard_Real x,y;
Standard_Integer i;
TColgp_Array1OfPnt2d Nodes(1, nbNodes);
for (i = 1; i <= nbNodes; i++) {
IS >> x >> y;
Nodes(i).SetCoord(x,y);
}
Handle(Poly_Polygon2D) P =
new Poly_Polygon2D(Nodes);
P->Deflection(d);
return P;
}
//=======================================================================
//function : ComputeNormals
//purpose :
//=======================================================================
void Poly::ComputeNormals(const Handle(Poly_Triangulation)& Tri)
{
const TColgp_Array1OfPnt& arrNodes = Tri->Nodes();
const Poly_Array1OfTriangle & arrTri = Tri->Triangles();
Standard_Integer nbNormVal = Tri->NbNodes() * 3;
const Handle(TShort_HArray1OfShortReal) Normals =
new TShort_HArray1OfShortReal(1, nbNormVal);
Normals->Init(0.F);
Standard_ShortReal * arrNormal = &(Normals->ChangeValue(1));
Standard_Real aCoord[3];
Standard_Integer iNode[3] = {0, 0, 0};
Standard_Integer iN, iTri;
const Standard_Real eps2 = Precision::Confusion()*Precision::Confusion();
for (iTri = 1; iTri <= arrTri.Length(); iTri++) {
// Get the nodes of the current triangle
arrTri(iTri).Get (iNode[0], iNode[1], iNode[2]);
const gp_XYZ aVec[2] = {
arrNodes(iNode[1]).XYZ() - arrNodes(iNode[0]).XYZ(),
arrNodes(iNode[2]).XYZ() - arrNodes(iNode[0]).XYZ()
};
// Find the normal vector of the current triangle
gp_XYZ aNorm = aVec[0] ^ aVec[1];
const Standard_Real aMod = aNorm.SquareModulus();
if (aMod > eps2) {
aNorm /= sqrt(aMod);
aNorm.Coord (aCoord[0], aCoord[1], aCoord[2]);
iNode[0] = (iNode[0]-1)*3;
iNode[1] = (iNode[1]-1)*3;
iNode[2] = (iNode[2]-1)*3;
arrNormal[iNode[0]+0] += (Standard_ShortReal)aCoord[0];
arrNormal[iNode[0]+1] += (Standard_ShortReal)aCoord[1];
arrNormal[iNode[0]+2] += (Standard_ShortReal)aCoord[2];
arrNormal[iNode[1]+0] += (Standard_ShortReal)aCoord[0];
arrNormal[iNode[1]+1] += (Standard_ShortReal)aCoord[1];
arrNormal[iNode[1]+2] += (Standard_ShortReal)aCoord[2];
arrNormal[iNode[2]+0] += (Standard_ShortReal)aCoord[0];
arrNormal[iNode[2]+1] += (Standard_ShortReal)aCoord[1];
arrNormal[iNode[2]+2] += (Standard_ShortReal)aCoord[2];
}
}
// Normalize all vectors
for (iN = 0; iN < nbNormVal; iN+=3) {
Standard_Real aMod (arrNormal[iN+0]*arrNormal[iN+0] +
arrNormal[iN+1]*arrNormal[iN+1] +
arrNormal[iN+2]*arrNormal[iN+2]);
if (aMod < eps2) {
arrNormal[iN+0] = 0.f;
arrNormal[iN+1] = 0.f;
arrNormal[iN+2] = 1.f;
} else {
aMod = sqrt(aMod);
arrNormal[iN+0] = Standard_ShortReal(arrNormal[iN+0]/aMod);
arrNormal[iN+1] = Standard_ShortReal(arrNormal[iN+1]/aMod);
arrNormal[iN+2] = Standard_ShortReal(arrNormal[iN+2]/aMod);
}
}
Tri->SetNormals(Normals);
}

53
src/Poly/Poly_CoherentLink.cxx Executable file
View File

@@ -0,0 +1,53 @@
// File: Poly_CoherentLink.cxx
// Created: 03.01.08 09:27
// Author: Alexander GRIGORIEV
// Copyright: Open Cascade 2008
#include <Poly_CoherentLink.hxx>
#include <Poly_CoherentTriangle.hxx>
#include <Standard_ProgramError.hxx>
//=======================================================================
//function : Poly_CoherentLink()
//purpose : Empty Constructor
//=======================================================================
Poly_CoherentLink::Poly_CoherentLink ()
: myAttribute (0L)
{
myNode[0] = -1;
myNode[1] = -1;
myOppositeNode[0] = -1;
myOppositeNode[1] = -1;
}
//=======================================================================
//function : Poly_CoherentLink()
//purpose : Constructor
//=======================================================================
Poly_CoherentLink::Poly_CoherentLink (const Poly_CoherentTriangle& theTri,
Standard_Integer iSide)
: myAttribute (0L)
{
static const Standard_Integer ind[] = { 1, 2, 0, 1 };
Standard_ProgramError_Raise_if(iSide < 0 || iSide > 2,
"Poly_CoherentLink::Poly_CoherentLink: "
"Wrong iSide parameter");
const Standard_Integer aNodeInd[2] = {
theTri.Node(ind[iSide+0]),
theTri.Node(ind[iSide+1])
};
if (aNodeInd[0] < aNodeInd[1]) {
myNode[0] = aNodeInd[0];
myNode[1] = aNodeInd[1];
myOppositeNode[0] = theTri.Node(iSide);
myOppositeNode[1] = theTri.GetConnectedNode(iSide);
} else {
myNode[0] = aNodeInd[1];
myNode[1] = aNodeInd[0];
myOppositeNode[0] = theTri.GetConnectedNode(iSide);
myOppositeNode[1] = theTri.Node(iSide);
}
}

124
src/Poly/Poly_CoherentLink.hxx Executable file
View File

@@ -0,0 +1,124 @@
// File: Poly_CoherentLink.hxx
// Created: 25.12.07 12:47
// Author: Alexander GRIGORIEV
// Copyright: Open Cascade 2007
#ifndef Poly_CoherentLink_HeaderFile
#define Poly_CoherentLink_HeaderFile
#include <Standard_TypeDef.hxx>
class Poly_CoherentTriangle;
class Poly_CoherentTriangulation;
/**
* Link between two mesh nodes that is created by existing triangle(s).
* Keeps reference to the opposite node of each incident triangle.
* The referred node with index "0" is always on the left side of the link,
* the one with the index "1" is always on the right side.
* It is possible to find both incident triangles using the method
* Poly_CoherentTriangulation::FindTriangle().
* <p>
* Any Link can store an arbitrary pointer that is called Attribute.
*/
class Poly_CoherentLink
{
public:
// ---------- PUBLIC METHODS ----------
/**
* Empty constructor.
*/
Standard_EXPORT Poly_CoherentLink ();
/**
* Constructor. Creates a Link that has no reference to 'opposite nodes'.
* This constructor is useful to create temporary object that is not
* inserted into any existing triangulation.
*/
inline Poly_CoherentLink (const Standard_Integer iNode0,
const Standard_Integer iNode1)
: myAttribute (0L)
{
myNode[0] = iNode0; myNode[1] = iNode1;
myOppositeNode[0] = -1; myOppositeNode[1] = -1;
}
/**
* Constructor, takes a triangle and a side. A link is created always such
* that myNode[0] < myNode[1]. Unlike the previous constructor, this one
* assigns the 'opposite node' fields. This constructor is used when a
* link is inserted into a Poly_CoherentTriangulation structure.
* @param theTri
* Triangle containing the link that is created
* @param iSide
* Can be 0, 1 or 2. Index of the node
*/
Standard_EXPORT Poly_CoherentLink (const Poly_CoherentTriangle& theTri,
Standard_Integer iSide);
/**
* Return the node index in the current triangulation.
* @param ind
* 0 or 1 making distinction of the two nodes that constitute the Link.
* Node(0) always returns a smaller number than Node(1).
*/
inline Standard_Integer Node (const Standard_Integer ind) const
{ return myNode[ind & 0x1]; }
/**
* Return the opposite node (belonging to the left or right incident triangle)
* index in the current triangulation.
* @param ind
* 0 or 1 making distinction of the two involved triangles: 0 on the left,
* 1 on the right side of the Link.
*/
inline Standard_Integer OppositeNode (const Standard_Integer ind) const
{ return myOppositeNode[ind & 0x1]; }
/**
* Query the attribute of the Link.
*/
inline Standard_Address GetAttribute () const
{ return myAttribute; }
/**
* Set the attribute of the Link.
*/
inline void SetAttribute (const Standard_Address theAtt)
{ myAttribute = theAtt; }
/**
* Query the status of the link - if it is an invalid one.
* An invalid link has Node members equal to -1.
*/
inline Standard_Boolean IsEmpty () const
{ return myNode[0] < 0 || myNode[1] < 0; }
/**
* Invalidate this Link.
*/
inline void Nullify ()
{
myNode[0] = -1; myNode[1] = -1;
myOppositeNode[0] = -1; myOppositeNode[1] = -1;
}
protected:
// ---------- PROTECTED METHODS ----------
private:
// ---------- PRIVATE FIELDS ----------
Standard_Integer myNode[2];
Standard_Integer myOppositeNode[2];
Standard_Address myAttribute;
friend class Poly_CoherentTriangulation;
};
#endif

104
src/Poly/Poly_CoherentNode.cxx Executable file
View File

@@ -0,0 +1,104 @@
// File: Poly_CoherentNode.cxx
// Created: 14.12.07 07:32
// Author: Alexander GRIGORIEV
// Copyright: Open Cascade 2007
#include <Poly_CoherentNode.hxx>
#include <Poly_CoherentTriangle.hxx>
#ifdef WNT
#pragma warning(disable:4291 4996)
#endif
//=======================================================================
//function : Clear
//purpose :
//=======================================================================
void Poly_CoherentNode::Clear (const Handle_NCollection_BaseAllocator& theAlloc)
{
Poly_CoherentTriPtr::RemoveList (myTriangles, theAlloc);
myUV[0] = Precision::Infinite();
myUV[1] = Precision::Infinite();
myNormal[0] = 0.f;
myNormal[1] = 0.f;
myNormal[2] = 0.f;
SetCoord(0., 0., 0.);
}
//=======================================================================
//function : SetNormal
//purpose : Define the normal vector in the Node.
//=======================================================================
void Poly_CoherentNode::SetNormal (const gp_XYZ& theVector)
{
myNormal[0] = static_cast<Standard_ShortReal>(theVector.X());
myNormal[1] = static_cast<Standard_ShortReal>(theVector.Y());
myNormal[2] = static_cast<Standard_ShortReal>(theVector.Z());
}
//=======================================================================
//function : AddTriangle
//purpose :
//=======================================================================
void Poly_CoherentNode::AddTriangle
(const Poly_CoherentTriangle& theTri,
const Handle_NCollection_BaseAllocator& theAlloc)
{
if (myTriangles == NULL)
myTriangles = new (theAlloc) Poly_CoherentTriPtr(theTri);
else
myTriangles->Prepend(&theTri, theAlloc);
}
//=======================================================================
//function : RemoveTriangle
//purpose :
//=======================================================================
Standard_Boolean Poly_CoherentNode::RemoveTriangle
(const Poly_CoherentTriangle& theTri,
const Handle_NCollection_BaseAllocator& theAlloc)
{
Standard_Boolean aResult(Standard_False);
if (&myTriangles->GetTriangle() == &theTri) {
Poly_CoherentTriPtr * aLostPtr = myTriangles;
if (myTriangles == &myTriangles->Next())
myTriangles = 0L;
else
myTriangles = &myTriangles->Next();
Poly_CoherentTriPtr::Remove(aLostPtr, theAlloc);
aResult = Standard_True;
} else {
Poly_CoherentTriPtr::Iterator anIter(* myTriangles);
for (anIter.Next(); anIter.More(); anIter.Next())
if (&anIter.Value() == &theTri) {
Poly_CoherentTriPtr::Remove
(const_cast<Poly_CoherentTriPtr *>(&anIter.PtrValue()), theAlloc);
aResult = Standard_True;
break;
}
}
return aResult;
}
//=======================================================================
//function : Dump
//purpose :
//=======================================================================
void Poly_CoherentNode::Dump(Standard_OStream& theStream) const
{
char buf[256];
sprintf (buf, " X =%9.4f; Y =%9.4f; Z =%9.4f", X(), Y(), Z());
theStream << buf << endl;
Poly_CoherentTriPtr::Iterator anIter(* myTriangles);
for (; anIter.More(); anIter.Next()) {
const Poly_CoherentTriangle& aTri = anIter.Value();
sprintf (buf, " %5d %5d %5d", aTri.Node(0),aTri.Node(1),aTri.Node(2));
theStream << buf << endl;
}
}

157
src/Poly/Poly_CoherentNode.hxx Executable file
View File

@@ -0,0 +1,157 @@
// File: Poly_CoherentNode.hxx
// Created: 08.12.07 10:45
// Author: Alexander GRIGORIEV
// Copyright: Open Cascade 2007
#ifndef Poly_CoherentNode_HeaderFile
#define Poly_CoherentNode_HeaderFile
#include <gp_XYZ.hxx>
#include <Poly_CoherentTriPtr.hxx>
#include <Precision.hxx>
class NCollection_BaseAllocator;
/**
* Node of coherent triangulation. Contains:
* <ul>
* <li>Coordinates of a 3D point defining the node location</li>
* <li>2D point coordinates</li>
* <li>List of triangles that use this Node</li>
* <li>Integer index, normally the index of the node in the original
* triangulation</li>
* </ul>
*/
class Poly_CoherentNode : public gp_XYZ
{
public:
// ---------- PUBLIC METHODS ----------
/**
* Empty constructor.
*/
inline Poly_CoherentNode ()
: gp_XYZ (0., 0., 0.),
myTriangles (0L),
myIndex (-1)
{ myUV[0] = Precision::Infinite(); myUV[1] = Precision::Infinite(); }
/**
* Constructor.
*/
inline Poly_CoherentNode (const gp_XYZ& thePnt)
: gp_XYZ (thePnt),
myTriangles (0L),
myIndex (-1)
{ myUV[0] = Precision::Infinite(); myUV[1] = Precision::Infinite(); myNormal[0] = 0.f; myNormal[1] = 0.f; myNormal[2] = 0.f; }
/**
* Set the UV coordinates of the Node.
*/
inline void SetUV (const Standard_Real theU,
const Standard_Real theV)
{ myUV[0] = theU; myUV[1] = theV; }
/**
* Get U coordinate of the Node.
*/
inline Standard_Real GetU () const
{ return myUV[0]; }
/**
* Get V coordinate of the Node.
*/
inline Standard_Real GetV () const
{ return myUV[1]; }
/**
* Define the normal vector in the Node.
*/
Standard_EXPORT void SetNormal (const gp_XYZ& theVector);
/**
* Query if the Node contains a normal vector.
*/
inline Standard_Boolean HasNormal () const
{ return ((myNormal[0]*myNormal[0] + myNormal[1]*myNormal[1] +
myNormal[2]*myNormal[2]) > Precision::Confusion()); }
/**
* Get the stored normal in the node.
*/
inline gp_XYZ GetNormal () const
{ return gp_XYZ (myNormal[0], myNormal[1], myNormal[2]); }
/**
* Set the value of node Index.
*/
inline void SetIndex (const Standard_Integer theIndex)
{ myIndex = theIndex; }
/**
* Get the value of node Index.
*/
inline Standard_Integer GetIndex () const
{ return myIndex; }
/**
* Check if this is a free node, i.e., a node without a single
* incident triangle.
*/
inline Standard_Boolean IsFreeNode () const
{ return myTriangles == 0L; }
/**
* Reset the Node to void.
*/
Standard_EXPORT void Clear (const Handle_NCollection_BaseAllocator&);
/**
* Connect a triangle to this Node.
*/
Standard_EXPORT void AddTriangle
(const Poly_CoherentTriangle& theTri,
const Handle_NCollection_BaseAllocator& theA);
/**
* Disconnect a triangle from this Node.
*/
Standard_EXPORT Standard_Boolean
RemoveTriangle
(const Poly_CoherentTriangle& theTri,
const Handle_NCollection_BaseAllocator& theA);
/**
* Create an iterator of incident triangles.
*/
inline Poly_CoherentTriPtr::Iterator
TriangleIterator () const
{ return * myTriangles; }
Standard_EXPORT void Dump (Standard_OStream& theStream) const;
// /**
// * Destructor.
// */
// Standard_EXPORT virtual ~Poly_CoherentNode ();
protected:
// ---------- PROTECTED METHODS ----------
private:
// ---------- PRIVATE FIELDS ----------
Standard_Real myUV[2];
Poly_CoherentTriPtr * myTriangles;
Standard_Integer myIndex;
Standard_ShortReal myNormal[3];
};
#endif

107
src/Poly/Poly_CoherentTriPtr.cxx Executable file
View File

@@ -0,0 +1,107 @@
// File: Poly_CoherentTriPtr.cxx
// Created: 08.12.07 12:33
// Author: Alexander GRIGORIEV
// Copyright: Open Cascade 2007
#include <Poly_CoherentTriPtr.hxx>
#ifdef WNT
#pragma warning(disable:4291)
#endif
//=======================================================================
//function : Iterator::Next
//purpose :
//=======================================================================
void Poly_CoherentTriPtr::Iterator::Next ()
{
if (myCurrent)
{
myCurrent = myCurrent->myNext;
if (myCurrent == myFirst)
myCurrent = 0L;
}
}
//=======================================================================
//function : Append
//purpose :
//=======================================================================
void Poly_CoherentTriPtr::Append
(const Poly_CoherentTriangle * pTri,
const Handle_NCollection_BaseAllocator& theAlloc)
{
Handle(NCollection_BaseAllocator) anAlloc = theAlloc;
if (theAlloc.IsNull())
anAlloc = NCollection_BaseAllocator::CommonBaseAllocator();
Poly_CoherentTriPtr * aNewPtr = new (anAlloc) Poly_CoherentTriPtr(* pTri);
aNewPtr->myNext = myNext;
myNext->myPrevious = aNewPtr;
aNewPtr->myPrevious = this;
myNext = aNewPtr;
}
//=======================================================================
//function : Prepend
//purpose :
//=======================================================================
void Poly_CoherentTriPtr::Prepend
(const Poly_CoherentTriangle * pTri,
const Handle_NCollection_BaseAllocator& theAlloc)
{
Handle(NCollection_BaseAllocator) anAlloc = theAlloc;
if (theAlloc.IsNull())
anAlloc = NCollection_BaseAllocator::CommonBaseAllocator();
Poly_CoherentTriPtr * aNewPtr = new (anAlloc) Poly_CoherentTriPtr(* pTri);
aNewPtr->myPrevious = myPrevious;
myPrevious->myNext = aNewPtr;
aNewPtr->myNext = this;
myPrevious = aNewPtr;
}
//=======================================================================
//function : Remove
//purpose :
//=======================================================================
void Poly_CoherentTriPtr::Remove
(Poly_CoherentTriPtr * thePtr,
const Handle_NCollection_BaseAllocator& theAlloc)
{
Handle(NCollection_BaseAllocator) anAlloc = theAlloc;
if (theAlloc.IsNull())
anAlloc = NCollection_BaseAllocator::CommonBaseAllocator();
if (thePtr->myNext && thePtr->myPrevious) {
thePtr->myPrevious->myNext = thePtr->myNext;
thePtr->myNext->myPrevious = thePtr->myPrevious;
thePtr->myNext = thePtr;
thePtr->myPrevious = thePtr;
}
anAlloc->Free(thePtr);
}
//=======================================================================
//function : RemoveList
//purpose :
//=======================================================================
void Poly_CoherentTriPtr::RemoveList
(Poly_CoherentTriPtr * thePtr,
const Handle_NCollection_BaseAllocator& theAlloc)
{
Handle(NCollection_BaseAllocator) anAlloc = theAlloc;
if (theAlloc.IsNull())
anAlloc = NCollection_BaseAllocator::CommonBaseAllocator();
Poly_CoherentTriPtr * aPtr = thePtr;
do {
if (aPtr == 0L)
break;
Poly_CoherentTriPtr * aLostPtr = aPtr;
aPtr = aPtr->myNext;
anAlloc->Free(aLostPtr);
} while (aPtr != thePtr);
}

178
src/Poly/Poly_CoherentTriPtr.hxx Executable file
View File

@@ -0,0 +1,178 @@
// File: Poly_CoherentTriPtr.hxx
// Created: 08.12.07 11:52
// Author: Alexander GRIGORIEV
// Copyright: Open Cascade 2007
#ifndef Poly_CoherentTriPtr_HeaderFile
#define Poly_CoherentTriPtr_HeaderFile
#include <NCollection_BaseAllocator.hxx>
class Poly_CoherentTriangle;
#ifdef WNT
#pragma warning (push)
#pragma warning(disable:4355 4291) //'this' : used in base member initializer list
#endif
/**
* Implementation of both list node for Poly_CoherentTriangle type and
* round double-linked list of these nodes.
*/
class Poly_CoherentTriPtr
{
public:
/**
* Iterator class for this list of triangles. Because the list is round,
* an iteration can be started from any member and it finishes before taking
* this member again. The iteration sense is always forward (Next).
*/
class Iterator {
public:
//! Empty constructor
inline Iterator ()
: myFirst (0L),
myCurrent (0L)
{}
//! Constructor
inline Iterator (const Poly_CoherentTriPtr& thePtr)
: myFirst (&thePtr),
myCurrent (&thePtr)
{}
//! Query the triangle that started the current iteration.
inline const Poly_CoherentTriangle * First () const
{ return myFirst ? &myFirst->GetTriangle() : 0L; }
//! Query if there is available triangle pointer on this iteration
inline Standard_Boolean More () const
{ return myCurrent != 0L; }
//! Go to the next iteration.
Standard_EXPORT void Next ();
//! Get the current iterated triangle
inline const Poly_CoherentTriangle& Value () const
{ return myCurrent->GetTriangle(); }
//! Get the current iterated triangle (mutable)
inline Poly_CoherentTriangle& ChangeValue () const
{ return const_cast<Poly_CoherentTriangle&>(myCurrent->GetTriangle()); }
//! Get the current iterated pointer to triangle
inline const Poly_CoherentTriPtr& PtrValue() const
{ return * myCurrent; }
private:
const Poly_CoherentTriPtr * myFirst;
const Poly_CoherentTriPtr * myCurrent;
};
// ---------- PUBLIC METHODS ----------
/**
* Constructor.
*/
inline Poly_CoherentTriPtr (const Poly_CoherentTriangle& theTri)
: mypTriangle (&theTri),
myNext (this),
myPrevious (this)
{}
/**
* Operator new for dynamic allocations
*/
void* operator new (Standard_Size theSize,
const Handle(NCollection_BaseAllocator)& theAllocator)
{
return theAllocator->Allocate(theSize);
}
/**
* Query the stored pointer to Triangle.
*/
inline const Poly_CoherentTriangle&
GetTriangle () const
{ return * mypTriangle; }
/**
* Initialize this instance with a pointer to triangle.
*/
inline void SetTriangle (const Poly_CoherentTriangle * pTri)
{ mypTriangle = pTri; }
/**
* Query the next pointer in the list.
*/
inline Poly_CoherentTriPtr&
Next () const
{ return * myNext; }
/**
* Query the previous pointer in the list.
*/
inline Poly_CoherentTriPtr&
Previous () const
{ return * myPrevious; }
/**
* Append a pointer to triangle into the list after the current instance.
* @param pTri
* Triangle that is to be included in the list after this one.
* @param theA
* Allocator where the new pointer instance is created.
*/
Standard_EXPORT void Append (const Poly_CoherentTriangle * pTri,
const Handle_NCollection_BaseAllocator& theA);
/**
* Prepend a pointer to triangle into the list before the current instance.
* @param pTri
* Triangle that is to be included in the list before this one.
* @param theA
* Allocator where the new pointer instance is created.
*/
Standard_EXPORT void Prepend (const Poly_CoherentTriangle * pTri,
const Handle_NCollection_BaseAllocator& theA);
/**
* Remove a pointer to triangle from its list.
* @param thePtr
* This class instance that should be removed from its list.
* @param theA
* Allocator where the current pointer instance was created.
*/
Standard_EXPORT static void
Remove (Poly_CoherentTriPtr * thePtr,
const Handle_NCollection_BaseAllocator& theA);
/**
* Remove the list containing the given pointer to triangle.
*/
Standard_EXPORT static void
RemoveList (Poly_CoherentTriPtr * thePtr,
const Handle_NCollection_BaseAllocator&);
protected:
// ---------- PROTECTED METHODS ----------
/**
* Constructor.
*/
inline Poly_CoherentTriPtr (const Poly_CoherentTriangle * pTri)
: mypTriangle (pTri),
myNext (this),
myPrevious (this)
{}
private:
// ---------- PRIVATE FIELDS ----------
const Poly_CoherentTriangle * mypTriangle;
Poly_CoherentTriPtr * myNext;
Poly_CoherentTriPtr * myPrevious;
friend class Iterator;
};
#ifdef WNT
#pragma warning (pop)
#endif
#endif

View File

@@ -0,0 +1,280 @@
// File: Poly_CoherentTriangle.cxx
// Created: 25.11.07 13:54
// Author: Alexander GRIGORIEV
// Copyright: Open Cascade 2007
#include <Poly_CoherentTriangle.hxx>
#include <Standard_ProgramError.hxx>
//=======================================================================
//function : Poly_CoherentTriangle()
//purpose : Empty Constructor
//=======================================================================
Poly_CoherentTriangle::Poly_CoherentTriangle ()
: myNConnections (0)
{
myNodes[0] = -1;
myNodes[1] = -1;
myNodes[2] = -1;
myNodesOnConnected[0] = -1;
myNodesOnConnected[1] = -1;
myNodesOnConnected[2] = -1;
mypConnected[0] = 0L;
mypConnected[1] = 0L;
mypConnected[2] = 0L;
mypLink[0] = 0L;
mypLink[1] = 0L;
mypLink[2] = 0L;
}
//=======================================================================
//function : Poly_CoherentTriangle()
//purpose : Constructor
//=======================================================================
Poly_CoherentTriangle::Poly_CoherentTriangle (const Standard_Integer iNode0,
const Standard_Integer iNode1,
const Standard_Integer iNode2)
: myNConnections (0)
{
myNodes[0] = iNode0;
myNodes[1] = iNode1;
myNodes[2] = iNode2;
myNodesOnConnected[0] = -1;
myNodesOnConnected[1] = -1;
myNodesOnConnected[2] = -1;
mypConnected[0] = 0L;
mypConnected[1] = 0L;
mypConnected[2] = 0L;
mypLink[0] = 0L;
mypLink[1] = 0L;
mypLink[2] = 0L;
}
//=======================================================================
//function : SetConnection
//purpose :
//=======================================================================
Standard_Boolean Poly_CoherentTriangle::SetConnection
(const Standard_Integer iConn,
Poly_CoherentTriangle& theTr)
{
Standard_Boolean aResult(Standard_False);
static const Standard_Integer II[] = { 2, 0, 1, 2, 0 };
if (theTr.Node(0) == myNodes[II[iConn+2]]) {
if (theTr.Node(2) == myNodes[II[iConn]]) {
RemoveConnection(iConn);
myNodesOnConnected[iConn] = theTr.Node(1);
mypConnected[iConn] = &theTr;
myNConnections++;
theTr.RemoveConnection(1);
theTr.myNodesOnConnected[1] = myNodes[iConn];
theTr.mypConnected[1] = this;
theTr.myNConnections++;
aResult = Standard_True;
}
} else if (theTr.Node(1) == myNodes[II[iConn+2]]) {
if (theTr.Node(0) == myNodes[II[iConn]]) {
RemoveConnection(iConn);
myNodesOnConnected[iConn] = theTr.Node(2);
mypConnected[iConn] = &theTr;
myNConnections++;
theTr.RemoveConnection(2);
theTr.myNodesOnConnected[2] = myNodes[iConn];
theTr.mypConnected[2] = this;
theTr.myNConnections++;
aResult = Standard_True;
}
} else if (theTr.Node(2) == myNodes[II[iConn+2]]) {
if (theTr.Node(1) == myNodes[II[iConn]]) {
RemoveConnection(iConn);
myNodesOnConnected[iConn] = theTr.Node(0);
mypConnected[iConn] = &theTr;
myNConnections++;
theTr.RemoveConnection(0);
theTr.myNodesOnConnected[0] = myNodes[iConn];
theTr.mypConnected[0] = this;
theTr.myNConnections++;
aResult = Standard_True;
}
}
return aResult;
}
//=======================================================================
//function : SetConnection
//purpose :
//=======================================================================
Standard_Boolean Poly_CoherentTriangle::SetConnection
(Poly_CoherentTriangle& theTr)
{
Standard_Boolean aResult(Standard_False);
if (myNodes[0] == theTr.Node(0)) {
if (myNodes[1] == theTr.Node(2) && mypConnected[2] != &theTr) {
RemoveConnection(2);
myNodesOnConnected[2] = theTr.Node(1);
mypConnected[2] = &theTr;
myNConnections++;
theTr.RemoveConnection(1);
theTr.myNodesOnConnected[1] = myNodes[2];
theTr.mypConnected[1] = this;
theTr.myNConnections++;
aResult = Standard_True;
} else if (myNodes[2] == theTr.Node(1) && mypConnected[1] != &theTr) {
RemoveConnection(1);
myNodesOnConnected[1] = theTr.Node(2);
mypConnected[1] = &theTr;
myNConnections++;
theTr.RemoveConnection(2);
theTr.myNodesOnConnected[2] = myNodes[1];
theTr.mypConnected[2] = this;
theTr.myNConnections++;
aResult = Standard_True;
}
} else if (myNodes[0] == theTr.Node(1)) {
if (myNodes[1] == theTr.Node(0) && mypConnected[2] != &theTr) {
RemoveConnection(2);
myNodesOnConnected[2] = theTr.Node(2);
mypConnected[2] = &theTr;
myNConnections++;
theTr.RemoveConnection(2);
theTr.myNodesOnConnected[2] = myNodes[2];
theTr.mypConnected[2] = this;
theTr.myNConnections++;
aResult = Standard_True;
} else if (myNodes[2] == theTr.Node(2) && mypConnected[1] != &theTr) {
RemoveConnection(1);
myNodesOnConnected[1] = theTr.Node(0);
mypConnected[1] = &theTr;
myNConnections++;
theTr.RemoveConnection(0);
theTr.myNodesOnConnected[0] = myNodes[1];
theTr.mypConnected[0] = this;
theTr.myNConnections++;
aResult = Standard_True;
}
} else if (myNodes[0] == theTr.Node(2)) {
if (myNodes[1] == theTr.Node(1) && mypConnected[2] != &theTr) {
RemoveConnection(2);
myNodesOnConnected[2] = theTr.Node(0);
mypConnected[2] = &theTr;
myNConnections++;
theTr.RemoveConnection(0);
theTr.myNodesOnConnected[0] = myNodes[2];
theTr.mypConnected[0] = this;
theTr.myNConnections++;
aResult = Standard_True;
} else if (myNodes[2] == theTr.Node(0) && mypConnected[1] != &theTr) {
RemoveConnection(1);
myNodesOnConnected[1] = theTr.Node(1);
mypConnected[1] = &theTr;
myNConnections++;
theTr.RemoveConnection(1);
theTr.myNodesOnConnected[1] = myNodes[1];
theTr.mypConnected[1] = this;
theTr.myNConnections++;
aResult = Standard_True;
}
} else if (mypConnected[0] != &theTr) {
if (myNodes[1] == theTr.Node(0) && myNodes[2] == theTr.Node(2)) {
RemoveConnection(0);
myNodesOnConnected[0] = theTr.Node(1);
mypConnected[0] = &theTr;
myNConnections++;
theTr.RemoveConnection(1);
theTr.myNodesOnConnected[1] = myNodes[0];
theTr.mypConnected[1] = this;
theTr.myNConnections++;
aResult = Standard_True;
} else if (myNodes[1] == theTr.Node(2) && myNodes[2] == theTr.Node(1)) {
RemoveConnection(0);
myNodesOnConnected[0] = theTr.Node(0);
mypConnected[0] = &theTr;
myNConnections++;
theTr.RemoveConnection(0);
theTr.myNodesOnConnected[0] = myNodes[0];
theTr.mypConnected[0] = this;
theTr.myNConnections++;
aResult = Standard_True;
} else if (myNodes[1] == theTr.Node(1) && myNodes[2] == theTr.Node(0)) {
RemoveConnection(0);
myNodesOnConnected[0] = theTr.Node(2);
mypConnected[0] = &theTr;
myNConnections++;
theTr.RemoveConnection(2);
theTr.myNodesOnConnected[2] = myNodes[0];
theTr.mypConnected[2] = this;
theTr.myNConnections++;
aResult = Standard_True;
}
}
return aResult;
}
//=======================================================================
//function : RemoveConnection
//purpose :
//=======================================================================
void Poly_CoherentTriangle::RemoveConnection(const Standard_Integer iConn)
{
Poly_CoherentTriangle * pConnectedTri =
const_cast<Poly_CoherentTriangle *> (mypConnected[iConn]);
if (pConnectedTri) {
Standard_Integer iConn1(0);
if (pConnectedTri->mypConnected[0] != this) {
if (pConnectedTri->mypConnected[1] == this)
iConn1 = 1;
else if (pConnectedTri->mypConnected[2] == this)
iConn1 = 2;
else
Standard_ProgramError::Raise("Poly_CoherentTriangle::RemoveConnection: "
"wrong connection between triangles");
}
pConnectedTri->mypConnected[iConn1] = 0L;
pConnectedTri->myNodesOnConnected[iConn1] = -1;
pConnectedTri->myNConnections--;
mypConnected[iConn] = 0L;
myNodesOnConnected[iConn] = -1;
myNConnections--;
}
}
//=======================================================================
//function : RemoveConnection
//purpose :
//=======================================================================
Standard_Boolean Poly_CoherentTriangle::RemoveConnection
(Poly_CoherentTriangle& theTri)
{
const Standard_Integer iConn = FindConnection(theTri);
if (iConn >= 0)
RemoveConnection(iConn);
return (iConn >= 0);
}
//=======================================================================
//function : FindConnection
//purpose :
//=======================================================================
Standard_Integer Poly_CoherentTriangle::FindConnection
(const Poly_CoherentTriangle& theTri) const
{
Standard_Integer aResult;
if (mypConnected[0] == &theTri)
aResult = 0;
else if (mypConnected[1] == &theTri)
aResult = 1;
else if (mypConnected[2] == &theTri)
aResult = 2;
else
aResult = -1;
return aResult;
}

View File

@@ -0,0 +1,157 @@
// File: Poly_CoherentTriangle.hxx
// Created: 24.11.07 14:36
// Author: Alexander GRIGORIEV
// Copyright: Open Cascade 2007
#ifndef Poly_CoherentTriangle_HeaderFile
#define Poly_CoherentTriangle_HeaderFile
#include <Standard_TypeDef.hxx>
class Poly_CoherentTrianguation;
class Poly_CoherentLink;
/**
* Data class used in Poly_CoherentTriangultion.
* Implements a triangle with references to its neighbours.
*/
class Poly_CoherentTriangle
{
public:
// ---------- PUBLIC METHODS ----------
/**
* Empty constructor.
*/
Standard_EXPORT Poly_CoherentTriangle ();
/**
* Constructor.
*/
Standard_EXPORT Poly_CoherentTriangle (const Standard_Integer iNode0,
const Standard_Integer iNode1,
const Standard_Integer iNode2);
/**
* Query the node index in the position given by the parameter 'ind'
*/
inline Standard_Integer Node (const Standard_Integer ind) const
{ return myNodes[ind]; }
// /**
// * Set the Node at the given position 'ind'.
// */
// inline void SetNode (const Standard_Integer ind,
// const Standard_Integer iNode)
// { myNodes[ind] = iNode; }
/**
* Query if this is a valid triangle.
*/
inline Standard_Boolean IsEmpty () const
{ return myNodes[0] < 0 || myNodes[1] < 0 || myNodes[2] < 0; }
/**
* Create connection with another triangle theTri.
* This method creates both connections: in this triangle and in theTri. You
* do not need to call the same method on triangle theTr.
* @param iConn
* Can be 0, 1 or 2 - index of the node that is opposite to the connection
* (shared link).
* @param theTr
* Triangle that is connected on the given link.
* @return
* True if successful, False if the connection is rejected
* due to improper topology.
*/
Standard_EXPORT Standard_Boolean
SetConnection (const Standard_Integer iConn,
Poly_CoherentTriangle& theTr);
/**
* Create connection with another triangle theTri.
* This method creates both connections: in this triangle and in theTri.
* This method is slower than the previous one, because it makes analysis
* what sides of both triangles are connected.
* @param theTri
* Triangle that is connected.
* @return
* True if successful, False if the connection is rejected
* due to improper topology.
*/
Standard_EXPORT Standard_Boolean
SetConnection (Poly_CoherentTriangle& theTri);
/**
* Remove the connection with the given index.
* @param iConn
* Can be 0, 1 or 2 - index of the node that is opposite to the connection
* (shared link).
*/
Standard_EXPORT void RemoveConnection(const Standard_Integer iConn);
/**
* Remove the connection with the given Triangle.
* @return
* True if successfuol or False if the connection has not been found.
*/
Standard_EXPORT Standard_Boolean
RemoveConnection(Poly_CoherentTriangle& theTri);
/**
* Query the number of connected triangles.
*/
inline Standard_Integer NConnections () const
{ return myNConnections; }
/**
* Query the connected node on the given side.
* Returns -1 if there is no connection on the specified side.
*/
inline Standard_Integer GetConnectedNode(const Standard_Integer iConn) const
{ return myNodesOnConnected[iConn]; }
/**
* Query the connected triangle on the given side.
* Returns NULL if there is no connection on the specified side.
*/
inline const Poly_CoherentTriangle *
GetConnectedTri (const Standard_Integer iConn) const
{ return mypConnected[iConn]; }
/**
* Query the Link associate with the given side of the Triangle.
* May return NULL if there are no links in the triangulation.
*/
inline const Poly_CoherentLink *
GetLink (const Standard_Integer iLink) const
{ return mypLink[iLink]; }
/**
* Retuns the index of the connection with the given triangle, or -1 if not
* found.
*/
Standard_EXPORT Standard_Integer
FindConnection (const Poly_CoherentTriangle&) const;
protected:
// ---------- PROTECTED METHODS ----------
private:
// ---------- PRIVATE FIELDS ----------
Standard_Integer myNConnections;
Standard_Integer myNodes[3];
Standard_Integer myNodesOnConnected[3];
const Poly_CoherentTriangle * mypConnected[3];
const Poly_CoherentLink * mypLink[3];
friend class Poly_CoherentTriangulation;
};
#endif

View File

@@ -0,0 +1,750 @@
// File: Poly_CoherentTriangulation.cxx
// Created: 08.12.07 13:19
// Author: Alexander GRIGORIEV
// Copyright: Open CASCADE SAS 2007
#include <Poly_CoherentTriangulation.hxx>
#include <Poly_Triangulation.hxx>
#include <Poly_Array1OfTriangle.hxx>
#include <NCollection_List.hxx>
#include <Precision.hxx>
#include <Standard_ProgramError.hxx>
#include <TColgp_Array1OfPnt.hxx>
#include <TColgp_Array1OfPnt2d.hxx>
#include <TShort_Array1OfShortReal.hxx>
#include <TShort_HArray1OfShortReal.hxx>
IMPLEMENT_STANDARD_HANDLE (Poly_CoherentTriangulation, Standard_Transient)
IMPLEMENT_STANDARD_RTTIEXT (Poly_CoherentTriangulation, Standard_Transient)
//=======================================================================
//function : Poly_CoherentTriangulation
//purpose : Empty constructor
//=======================================================================
Poly_CoherentTriangulation::Poly_CoherentTriangulation
(const Handle_NCollection_BaseAllocator& theAlloc)
: myAlloc (theAlloc.IsNull() ? NCollection_BaseAllocator::CommonBaseAllocator()
: theAlloc),
myDeflection (0.)
{}
//=======================================================================
//function : Poly_CoherentTriangulation
//purpose : Constructor
//=======================================================================
Poly_CoherentTriangulation::Poly_CoherentTriangulation
(const Handle(Poly_Triangulation)& theTriangulation,
const Handle_NCollection_BaseAllocator& theAlloc)
: myAlloc (theAlloc.IsNull() ? NCollection_BaseAllocator::CommonBaseAllocator()
: theAlloc)
{
if (theTriangulation.IsNull() == Standard_False) {
const TColgp_Array1OfPnt& arrNodes = theTriangulation->Nodes();
const Poly_Array1OfTriangle& arrTriangle = theTriangulation->Triangles();
const Standard_Integer nNodes = theTriangulation->NbNodes();
const Standard_Integer nTri = theTriangulation->NbTriangles();
Standard_Integer i;
// Copy the nodes
for (i = 0; i < nNodes; i++) {
const Standard_Integer anOldInd = i + arrNodes.Lower();
const Standard_Integer aNewInd = SetNode(arrNodes(anOldInd).XYZ(), i);
Poly_CoherentNode& aCopiedNode = myNodes(aNewInd);
aCopiedNode.SetIndex(anOldInd);
}
// Copy the triangles
for (i = 0; i < nTri; i++) {
Standard_Integer iNode[3];
arrTriangle(i + arrTriangle.Lower()).Get(iNode[0], iNode[1], iNode[2]);
if (iNode[0] != iNode[1] && iNode[1] != iNode[2] && iNode[2] != iNode[0])
AddTriangle (iNode[0]-1, iNode[1]-1, iNode[2]-1);
}
// Copy UV coordinates of nodes
if (theTriangulation->HasUVNodes()) {
const TColgp_Array1OfPnt2d& arrNodes2d = theTriangulation->UVNodes();
for (i = 0; i < nNodes; i++) {
const gp_Pnt2d& anUV = arrNodes2d(i + arrNodes2d.Lower());
myNodes(i).SetUV(anUV.X(), anUV.Y());
}
}
// Copy the normals at nodes
if (theTriangulation->HasNormals()) {
const TShort_Array1OfShortReal& arrNorm = theTriangulation->Normals();
for (i = 0; i < nNodes; i++) {
const gp_XYZ aNormal (arrNorm(3 * i + 0 + arrNorm.Lower()),
arrNorm(3 * i + 1 + arrNorm.Lower()),
arrNorm(3 * i + 2 + arrNorm.Lower()));
myNodes(i).SetNormal(aNormal);
}
}
myDeflection = theTriangulation->Deflection();
}
}
//=======================================================================
//function : ~Poly_CoherentTriangulation()
//purpose : Destructor
//=======================================================================
Poly_CoherentTriangulation::~Poly_CoherentTriangulation ()
{
NCollection_Vector<Poly_CoherentNode>::Iterator anIter (myNodes);
for (; anIter.More(); anIter.Next()) {
anIter.ChangeValue().Clear(myAlloc);
}
}
//=======================================================================
//function : GetTriangulation
//purpose :
//=======================================================================
Handle_Poly_Triangulation Poly_CoherentTriangulation::GetTriangulation() const
{
Handle(Poly_Triangulation) aResult;
const Standard_Integer nNodes = NNodes();
const Standard_Integer nTriangles = NTriangles();
if (nNodes > 0 && nTriangles > 0) {
aResult = new Poly_Triangulation(nNodes, nTriangles, Standard_True);
const Handle(TShort_HArray1OfShortReal) harrNormal =
new TShort_HArray1OfShortReal(1, 3 * nNodes);
Standard_ShortReal * arrNormal = &harrNormal->ChangeValue(1);
TColgp_Array1OfPnt& arrNodes = aResult->ChangeNodes();
TColgp_Array1OfPnt2d& arrNodesUV = aResult->ChangeUVNodes();
Poly_Array1OfTriangle& arrTriangle = aResult->ChangeTriangles();
NCollection_Vector<Standard_Integer> vecNodeId;
Standard_Integer i, aCount(0);
Standard_Boolean hasUV (Standard_False);
Standard_Boolean hasNormals (Standard_False);
// Copy the nodes (3D and 2D coordinates)
for (i = 0; i < myNodes.Length(); i++) {
const Poly_CoherentNode& aNode = myNodes(i);
if (aNode.IsFreeNode())
vecNodeId.SetValue(i, 0);
else {
const gp_XYZ aNormal = aNode.GetNormal();
arrNormal[3 * aCount + 0] = static_cast<Standard_ShortReal>(aNormal.X());
arrNormal[3 * aCount + 1] = static_cast<Standard_ShortReal>(aNormal.Y());
arrNormal[3 * aCount + 2] = static_cast<Standard_ShortReal>(aNormal.Z());
vecNodeId.SetValue(i, ++aCount);
arrNodes.SetValue(aCount, aNode);
arrNodesUV.SetValue(aCount, gp_Pnt2d(aNode.GetU(), aNode.GetV()));
if (aNode.GetU()*aNode.GetU() + aNode.GetV()*aNode.GetV() >
Precision::Confusion())
hasUV = Standard_True;
if (aNormal.SquareModulus() > Precision::Confusion())
hasNormals = Standard_True;
}
}
if (hasUV == Standard_False)
aResult->RemoveUVNodes();
// Copy the triangles
aCount = 0;
NCollection_Vector<Poly_CoherentTriangle>::Iterator anIterT (myTriangles);
for (; anIterT.More(); anIterT.Next()) {
const Poly_CoherentTriangle& aTri = anIterT.Value();
if (aTri.IsEmpty() == Standard_False) {
const Poly_Triangle aPolyTriangle (vecNodeId(aTri.Node(0)),
vecNodeId(aTri.Node(1)),
vecNodeId(aTri.Node(2)));
arrTriangle.SetValue(++aCount, aPolyTriangle);
}
}
if (hasNormals)
aResult->SetNormals (harrNormal);
aResult->Deflection(myDeflection);
}
return aResult;
}
//=======================================================================
//function : GetFreeNodes
//purpose : Create a list of free nodes.
//=======================================================================
Standard_Boolean Poly_CoherentTriangulation::GetFreeNodes
(NCollection_List<Standard_Integer>& lstNodes) const
{
lstNodes.Clear();
Standard_Integer i;
for (i = 0; i < myNodes.Length(); i++) {
const Poly_CoherentNode& aNode = myNodes(i);
if (aNode.IsFreeNode())
lstNodes.Append(i);
}
return !lstNodes.IsEmpty();
}
//=======================================================================
//function : RemoveDegenerated
//purpose : Find and remove degenerated triangles in Triangulation.
//=======================================================================
Standard_Boolean Poly_CoherentTriangulation::RemoveDegenerated
(const Standard_Real theTol,
NCollection_List<Poly_CoherentTriangulation::TwoIntegers> * pLstRemovedNode)
{
Standard_Boolean aResult(Standard_False);
const Standard_Real aTol2 = theTol * theTol;
const Standard_Integer ind0[] = {2, 0, 1, 2, 0};
const Standard_Integer * ind = &ind0[1];
if (pLstRemovedNode)
pLstRemovedNode->Clear();
//NCollection_Vector<Poly_CoherentTriangle>::Iterator anIterT(myTriangles);
Poly_CoherentTriangulation::IteratorOfTriangle anIterT(this);
for (; anIterT.More(); anIterT.Next()) {
Poly_CoherentTriangle& aTri = anIterT.ChangeValue();
Poly_CoherentNode * pNode[3] = {
&ChangeNode(aTri.Node(0)),
&ChangeNode(aTri.Node(1)),
&ChangeNode(aTri.Node(2))
};
const Standard_Real aLen2[3] = {
pNode[2]->Subtracted(* pNode[1]).SquareModulus(),
pNode[0]->Subtracted(* pNode[2]).SquareModulus(),
pNode[1]->Subtracted(* pNode[0]).SquareModulus()
};
for (Standard_Integer i = 0; i < 3; i++) {
if (aLen2[i] < aTol2) {
const Standard_Integer im1(aTri.Node(ind[i-1]));
const Standard_Integer ip1(aTri.Node(ind[i+1]));
// Disconnect from both neighbours
Poly_CoherentTriangle * pTriConn[2] = {
const_cast<Poly_CoherentTriangle *>(aTri.GetConnectedTri(ind[i-1])),
const_cast<Poly_CoherentTriangle *>(aTri.GetConnectedTri(ind[i+1]))
};
RemoveTriangle(aTri);
// Reconnect all triangles from Node(ind[i+1]) to Node(ind[i-1])
Poly_CoherentTriPtr::Iterator anIterConn =
pNode[ind[i+1]]->TriangleIterator();
for (; anIterConn.More(); anIterConn.Next()) {
Poly_CoherentTriangle& aTriConn = anIterConn.ChangeValue();
if (&aTriConn != &aTri) {
if (aTriConn.Node(0) == ip1)
aTriConn.myNodes[0] = im1;
else if (aTriConn.Node(1) == ip1)
aTriConn.myNodes[1] = im1;
else if (aTriConn.Node(2) == ip1)
aTriConn.myNodes[2] = im1;
pNode[ind[i+1]]->RemoveTriangle(aTriConn, myAlloc);
pNode[ind[i-1]]->AddTriangle(aTriConn, myAlloc);
}
}
// Set the new mutual connection between the neighbours of the
// removed degenerated triangle.
if (pTriConn[0] && pTriConn[1]) {
pTriConn[0]->SetConnection(* pTriConn[1]);
}
if (pLstRemovedNode) {
pLstRemovedNode->Append(TwoIntegers(ip1, im1));
}
aResult = Standard_True;
break;
}
}
}
return aResult;
}
//=======================================================================
//function : IteratorOfTriangle::IteratorOfTriangle
//purpose : Constructor
//=======================================================================
Poly_CoherentTriangulation::IteratorOfTriangle::IteratorOfTriangle
(const Handle_Poly_CoherentTriangulation& theTri)
{
if (!theTri.IsNull()) {
Init(theTri->myTriangles);
while (More()) {
const Poly_CoherentTriangle& aTri = Value();
if (aTri.IsEmpty() == Standard_False)
break;
Poly_BaseIteratorOfCoherentTriangle::Next();
}
}
}
//=======================================================================
//function : IteratorOfTriangle::Next
//purpose :
//=======================================================================
void Poly_CoherentTriangulation::IteratorOfTriangle::Next()
{
Poly_BaseIteratorOfCoherentTriangle::Next();
while (More()) {
const Poly_CoherentTriangle& aTri = Value();
if (aTri.IsEmpty() == Standard_False)
break;
Poly_BaseIteratorOfCoherentTriangle::Next();
}
}
//=======================================================================
//function : IteratorOfNode::IteratorOfNode
//purpose : Constructor
//=======================================================================
Poly_CoherentTriangulation::IteratorOfNode::IteratorOfNode
(const Handle_Poly_CoherentTriangulation& theTri)
{
if (!theTri.IsNull()) {
Init(theTri->myNodes);
while (More()) {
if (Value().IsFreeNode() == Standard_False)
break;
Poly_BaseIteratorOfCoherentNode::Next();
}
}
}
//=======================================================================
//function : IteratorOfNode::Next
//purpose :
//=======================================================================
void Poly_CoherentTriangulation::IteratorOfNode::Next()
{
Poly_BaseIteratorOfCoherentNode::Next();
while (More()) {
if (Value().IsFreeNode() == Standard_False)
break;
Poly_BaseIteratorOfCoherentNode::Next();
}
}
//=======================================================================
//function : IteratorOfLink::IteratorOfLink
//purpose : Constructor
//=======================================================================
Poly_CoherentTriangulation::IteratorOfLink::IteratorOfLink
(const Handle_Poly_CoherentTriangulation& theTri)
{
if (!theTri.IsNull()) {
Init(theTri->myLinks);
while (More()) {
if (Value().IsEmpty() == Standard_False)
break;
Poly_BaseIteratorOfCoherentLink::Next();
}
}
}
//=======================================================================
//function : IteratorOfLink::Next
//purpose :
//=======================================================================
void Poly_CoherentTriangulation::IteratorOfLink::Next()
{
Poly_BaseIteratorOfCoherentLink::Next();
while (More()) {
if (Value().IsEmpty() == Standard_False)
break;
Poly_BaseIteratorOfCoherentLink::Next();
}
}
//=======================================================================
//function : NNodes
//purpose :
//=======================================================================
Standard_Integer Poly_CoherentTriangulation::NNodes () const
{
Standard_Integer aCount(0);
NCollection_Vector<Poly_CoherentNode>::Iterator anIter (myNodes);
for (; anIter.More(); anIter.Next())
if (anIter.Value().IsFreeNode() == Standard_False)
aCount++;
return aCount;
}
//=======================================================================
//function : NTriangles
//purpose :
//=======================================================================
Standard_Integer Poly_CoherentTriangulation::NTriangles () const
{
Standard_Integer aCount(0);
NCollection_Vector<Poly_CoherentTriangle>::Iterator anIter (myTriangles);
for (; anIter.More(); anIter.Next()) {
const Poly_CoherentTriangle& aTri = anIter.Value();
if (aTri.IsEmpty() == Standard_False)
aCount++;
}
return aCount;
}
//=======================================================================
//function : NLinks
//purpose :
//=======================================================================
Standard_Integer Poly_CoherentTriangulation::NLinks () const
{
Standard_Integer aCount(0);
NCollection_Vector<Poly_CoherentLink>::Iterator anIter (myLinks);
for (; anIter.More(); anIter.Next()) {
if (anIter.Value().IsEmpty() == Standard_False)
aCount++;
}
return aCount;
}
//=======================================================================
//function : SetNode
//purpose :
//=======================================================================
Standard_Integer Poly_CoherentTriangulation::SetNode
(const gp_XYZ& thePnt,
const Standard_Integer iNode)
{
Standard_Integer aResult = myNodes.Length();
if (iNode < 0)
myNodes.Append(Poly_CoherentNode(thePnt));
else {
myNodes.SetValue(iNode, Poly_CoherentNode(thePnt));
aResult = iNode;
}
return aResult;
}
//=======================================================================
//function : RemoveTriangle
//purpose :
//=======================================================================
Standard_Boolean Poly_CoherentTriangulation::RemoveTriangle
(Poly_CoherentTriangle& theTriangle)
{
Standard_Boolean aResult(Standard_False);
for (Standard_Integer i = 0; i < 3; i++) {
if (theTriangle.Node(i) >= 0) {
Poly_CoherentNode& aNode = myNodes(theTriangle.Node(i));
if (aNode.RemoveTriangle(theTriangle, myAlloc)) {
theTriangle.myNodes[i] = -1;
aResult = Standard_True;
}
// If Links exist in this Triangulation, remove or update a Link
Poly_CoherentLink * aLink =
const_cast<Poly_CoherentLink *>(theTriangle.mypLink[i]);
if (aLink) {
const Poly_CoherentTriangle * pTriOpp = theTriangle.GetConnectedTri(i);
Standard_Boolean toRemoveLink(Standard_True);
if (pTriOpp != 0L) {
// A neighbour is detected. If a Link exists on it, update it,
// otherwise remove this link
for (Standard_Integer j = 0; j < 3; j++) {
if (aLink == pTriOpp->GetLink(j)) {
if (aLink->OppositeNode(0) == theTriangle.Node(i)) {
aLink->myOppositeNode[0] = 0L;
toRemoveLink = Standard_False;
} else if (aLink->OppositeNode(1) == theTriangle.Node(i)) {
aLink->myOppositeNode[1] = 0L;
toRemoveLink = Standard_False;
}
break;
}
}
}
if (toRemoveLink)
RemoveLink(* aLink);
}
}
theTriangle.RemoveConnection(i);
}
return aResult;
}
//=======================================================================
//function : AddTriangle
//purpose :
//=======================================================================
Poly_CoherentTriangle * Poly_CoherentTriangulation::AddTriangle
(const Standard_Integer iNode0,
const Standard_Integer iNode1,
const Standard_Integer iNode2)
{
Poly_CoherentTriangle * pTriangle = 0L;
if (iNode0 >= 0 && iNode1 >= 0 && iNode2 >= 0)
{
pTriangle = & myTriangles.Append(Poly_CoherentTriangle());
ReplaceNodes(*pTriangle, iNode0, iNode1, iNode2);
}
return pTriangle;
}
//=======================================================================
//function : ReplaceNodes
//purpose :
//=======================================================================
Standard_Boolean Poly_CoherentTriangulation::ReplaceNodes
(Poly_CoherentTriangle& theTriangle,
const Standard_Integer iNode0,
const Standard_Integer iNode1,
const Standard_Integer iNode2)
{
if (!theTriangle.IsEmpty())
RemoveTriangle(theTriangle);
if (iNode0 >= 0 && iNode1 >= 0 && iNode2 >= 0)
{
theTriangle = Poly_CoherentTriangle (iNode0, iNode1, iNode2);
for (Standard_Integer i = 0; i < 3; i++) {
Poly_CoherentNode& aNode = myNodes(theTriangle.Node(i));
Poly_CoherentTriPtr::Iterator anIterT = aNode.TriangleIterator();
for (; anIterT.More(); anIterT.Next()) {
anIterT.ChangeValue().SetConnection(theTriangle);
}
aNode.AddTriangle(theTriangle, myAlloc);
}
// If Links exist in this Triangulation, create or update a Link
if (myLinks.Length() > 0) {
for (Standard_Integer i = 0; i < 3; i++) {
const Poly_CoherentTriangle * pTriOpp = theTriangle.GetConnectedTri(i);
Standard_Boolean toAddLink(Standard_True);
if (pTriOpp != 0L) {
// A neighbour is detected. If a Link exists on it, update it,
// otherwise create a new link.
for (Standard_Integer j = 0; j < 3; j++) {
if (theTriangle.Node(i) == pTriOpp->GetConnectedNode(j)) {
Poly_CoherentLink * aLink =
const_cast<Poly_CoherentLink *>(pTriOpp->GetLink(j));
if (aLink != 0L) {
if (aLink->OppositeNode(0) == pTriOpp->Node(j)) {
aLink->myOppositeNode[1] = theTriangle.Node(i);
toAddLink = Standard_False;
} else if (aLink->OppositeNode(1) == pTriOpp->Node(j)) {
aLink->myOppositeNode[0] = theTriangle.Node(i);
toAddLink = Standard_False;
}
}
break;
}
}
}
if (toAddLink) {
// No neighbor on this side, the new Link is created.
AddLink (theTriangle, i);
}
}
}
return Standard_True;
}
return Standard_False;
}
//=======================================================================
//function : RemoveLink
//purpose :
//=======================================================================
void Poly_CoherentTriangulation::RemoveLink (Poly_CoherentLink& theLink)
{
const Poly_CoherentTriangle * pTri[2] = { 0L, 0L };
if (FindTriangle (theLink, pTri)) {
for (Standard_Integer i = 0; i < 2; i++) {
const Standard_Integer iNode = theLink.OppositeNode(i);
if (iNode >= 0 && pTri[i] != 0L) {
if (iNode == pTri[i]->Node(0))
const_cast<Poly_CoherentTriangle *>(pTri[i])->mypLink[0] = 0L;
else if (iNode == pTri[i]->Node(1))
const_cast<Poly_CoherentTriangle *>(pTri[i])->mypLink[1] = 0L;
else if (iNode == pTri[i]->Node(2))
const_cast<Poly_CoherentTriangle *>(pTri[i])->mypLink[2] = 0L;
else
Standard_ProgramError("Poly_CoherentTriangulation::RemoveLink: "
" wrong connectivity between triangles");
}
}
}
theLink = Poly_CoherentLink();
}
//=======================================================================
//function : AddLink
//purpose :
//=======================================================================
Poly_CoherentLink * Poly_CoherentTriangulation::AddLink
(const Poly_CoherentTriangle& theTri,
const Standard_Integer theConn)
{
Poly_CoherentLink * pLink = 0L;
if (theTri.IsEmpty() == Standard_False) {
pLink = &myLinks.Append(Poly_CoherentLink (theTri, theConn));
const_cast<Poly_CoherentTriangle&>(theTri).mypLink[theConn] = pLink;
const Poly_CoherentTriangle* pTriOpp = theTri.GetConnectedTri(theConn);
if(!pTriOpp) return pLink;
if(pTriOpp->IsEmpty()) return pLink;
if (pTriOpp) {
if (pTriOpp->Node(0) == theTri.GetConnectedNode(theConn))
const_cast<Poly_CoherentTriangle *>(pTriOpp)->mypLink[0] = pLink;
else if (pTriOpp->Node(1) == theTri.GetConnectedNode(theConn))
const_cast<Poly_CoherentTriangle *>(pTriOpp)->mypLink[1] = pLink;
else if (pTriOpp->Node(2) == theTri.GetConnectedNode(theConn))
const_cast<Poly_CoherentTriangle *>(pTriOpp)->mypLink[2] = pLink;
else
Standard_ProgramError::Raise("Poly_CoherentTriangulation::AddLink: "
"Bad connectivity of triangles");
}
}
return pLink;
}
//=======================================================================
//function : FindTriangle
//purpose :
//=======================================================================
Standard_Boolean Poly_CoherentTriangulation::FindTriangle
(const Poly_CoherentLink& theLink,
const Poly_CoherentTriangle* pTri[2]) const
{
pTri[0] = 0L;
pTri[1] = 0L;
const Standard_Integer iNode0 = theLink.Node(0);
if (theLink.IsEmpty() == Standard_False &&
iNode0 < myNodes.Length() && theLink.Node(1) < myNodes.Length())
{
Poly_CoherentTriPtr::Iterator anIter0 = myNodes(iNode0).TriangleIterator();
for (; anIter0.More(); anIter0.Next()) {
const Poly_CoherentTriangle& aTri = anIter0.Value();
if (aTri.Node(0) == iNode0) {
if (aTri.Node(1) == theLink.Node(1))
pTri[0] = &aTri;
else if (aTri.Node(2) == theLink.Node(1))
pTri[1] = &aTri;
} else if (aTri.Node(1) == iNode0) {
if (aTri.Node(2) == theLink.Node(1))
pTri[0] = &aTri;
else if (aTri.Node(0) == theLink.Node(1))
pTri[1] = &aTri;
} else if (aTri.Node(2) == iNode0) {
if (aTri.Node(0) == theLink.Node(1))
pTri[0] = &aTri;
else if (aTri.Node(1) == theLink.Node(1))
pTri[1] = &aTri;
} else
Standard_ProgramError("Poly_CoherentTriangulation::FindTriangle : "
" Data incoherence detected");
if (pTri[0] && pTri[1])
break;
}
}
return (pTri[0] != 0L || pTri[1] != 0L);
}
//=======================================================================
//function : ComputeLinks
//purpose :
//=======================================================================
Standard_Integer Poly_CoherentTriangulation::ComputeLinks ()
{
myLinks.Clear();
NCollection_Vector<Poly_CoherentTriangle>::Iterator anIter (myTriangles);
for (; anIter.More(); anIter.Next()) {
const Poly_CoherentTriangle& aTriangle = anIter.Value();
if(aTriangle.IsEmpty()) continue;
if (aTriangle.Node(0) < aTriangle.Node(1))
AddLink (aTriangle, 2);
if (aTriangle.Node(1) < aTriangle.Node(2))
AddLink (aTriangle, 0);
if (aTriangle.Node(2) < aTriangle.Node(0))
AddLink (aTriangle, 1);
}
// Above algorithm does not create all boundary links, so
// it is necessary to check triangles and add absentee links
anIter.Init(myTriangles);
Standard_Integer i;
for (; anIter.More(); anIter.Next()) {
Poly_CoherentTriangle& aTriangle = anIter.ChangeValue();
if(aTriangle.IsEmpty()) continue;
for (i = 0; i < 3; ++i) {
if (aTriangle.mypLink[i] == 0L) {
AddLink(aTriangle, i);
}
}
}
return myLinks.Length();
}
//=======================================================================
//function : ClearLinks
//purpose :
//=======================================================================
void Poly_CoherentTriangulation::ClearLinks ()
{
myLinks.Clear();
NCollection_Vector<Poly_CoherentTriangle>::Iterator anIter (myTriangles);
for (; anIter.More(); anIter.Next()) {
Poly_CoherentTriangle& aTriangle = anIter.ChangeValue();
aTriangle.mypLink[0] = 0L;
aTriangle.mypLink[1] = 0L;
aTriangle.mypLink[2] = 0L;
}
}
//=======================================================================
//function : Clone
//purpose :
//=======================================================================
Handle(Poly_CoherentTriangulation) Poly_CoherentTriangulation::Clone
(const Handle_NCollection_BaseAllocator& theAlloc) const
{
Handle(Poly_CoherentTriangulation) newTri;
if (NTriangles() != 0 && NNodes() != 0) {
Handle(Poly_Triangulation) theTriangulation = GetTriangulation();
newTri = new Poly_CoherentTriangulation(theTriangulation, theAlloc);
newTri->SetDeflection(theTriangulation->Deflection());
}
return newTri;
}
//=======================================================================
//function : Dump
//purpose :
//=======================================================================
void Poly_CoherentTriangulation::Dump (Standard_OStream& theStream) const
{
for (Standard_Integer iNode = 0; iNode < myNodes.Length(); iNode++) {
const Poly_CoherentNode& aNode = myNodes(iNode);
if (aNode.IsFreeNode())
continue;
theStream << "Node " << iNode;
aNode.Dump(theStream);
}
}

View File

@@ -0,0 +1,405 @@
// File: Poly_CoherentTriangulation.hxx
// Created: 24.11.07 14:24
// Author: Alexander GRIGORIEV
// Copyright: Open Cascade 2007
#ifndef Poly_CoherentTriangulation_HeaderFile
#define Poly_CoherentTriangulation_HeaderFile
#include <Handle_Poly_Triangulation.hxx>
#include <Poly_CoherentNode.hxx>
#include <Poly_CoherentTriangle.hxx>
#include <Poly_CoherentLink.hxx>
#include <NCollection_Vector.hxx>
class Handle_Poly_CoherentTriangulation;
class Poly_CoherentTriangulation;
template <class A> class NCollection_List;
typedef NCollection_Vector<Poly_CoherentTriangle>::Iterator
Poly_BaseIteratorOfCoherentTriangle;
typedef NCollection_Vector<Poly_CoherentNode>::Iterator
Poly_BaseIteratorOfCoherentNode;
typedef NCollection_Vector<Poly_CoherentLink>::Iterator
Poly_BaseIteratorOfCoherentLink;
/**
* Triangulation structure that allows to:
* <ul>
* <li>Store the connectivity of each triangle with up to 3 neighbouring ones
* and with the corresponding 3rd nodes on them,</li>
* <li>Store the connectivity of each node with all triangles that share this
* node</li>
* <li>Add nodes and triangles to the structure,</li>
* <li>Find all triangles sharing a single or a couple of nodes</li>
* <li>Remove triangles from structure</li>
* <li>Optionally create Links between pairs of nodes according to the current
* triangulation.
* <li>Convert from/to Poly_Triangulation structure.</li>
* </ul>
* This class is useful for algorithms that need to analyse and/or edit a
* triangulated mesh -- for example for mesh refining. The connectivity model
* follows the idea that all Triangles in a mesh should have coherent orientation
* like on a surface of a solid body. Connections between more than 2 triangles
* are not suppoorted.
* @section Poly_CoherentTriangulation Architecture
* The data types used in this structure are:
* <ul>
* <li><b>Poly_CoherentNode</b>: Inherits go_XYZ therefore provides the full
* public API of gp_XYZ. Contains references to all incident triangles. You
* can add new nodes but you cannot remove existing ones. However each node
* that has no referenced triangle is considered as "free" (use the method
* IsFreeNode() to check this). Free nodes are not available to further
* processing, particularly they are not exported in Poly_Triangulation.
* </li>
* <li><b>Poly_CoherentTriangle</b>: Main data type. Refers three Nodes, three
* connected Triangles, three opposite (connected) Nodes and three Links.
* If there is boundary then 1, 2 or 3 references to Triangles/connected
* Nodes/Links are assigned to NULL (for pointers) or -1 (for integer
* node index).
* <br>
* You can find a triangle by one node using its triangle iterator or by
* two nodes - creating a temporary Poly_CoherentLink and calling the method
* FindTriangle().
* <br>
* Triangles can be removed but they are never deleted from
* the containing array. Removed triangles have all nodes equal to -1. You
* can use the method IsEmpty() to check that.
* </li>
* <li><b>Poly_CoherentLink</b>: Auxiliary data type. Normally the array of
* Links is empty, because for many algorithms it is sufficient to define
* only Triangles. You can explicitly create the Links at least once,
* calling the method ComputeLinks(). Each Link is oriented couple of
* Poly_CoherentNode (directed to the ascending Node index). It refers
* two connected triangulated Nodes - on the left and on the right,
* therefore a Poly_CoherentLink instance refers the full set of nodes
* that constitute a couple of connected Triangles. A boundary Link has
* either the first (left) or the second (right) connected node index
* equal to -1.
* <br>
* When the array of Links is created, all subsequent calls to AddTriangle
* and RemoveTriangle try to preserve the connectivity Triangle-Link in
* addition to the connectivity Triangle-Triangle. Particularly, new Links
* are created by method AddTriangle() and existing ones are removed by
* method RemoveTriangle(), in each case whenever necessary.
* <br>
* Similarly to Poly_CoherentTriangle, a Link can be removed but not
* destroyed separately from others. Removed Link can be recogniosed using
* the method IsEmpty(). To destroy all Links, call the method ClearLinks(),
* this method also nullifies Link references in all Triangles.
* </li>
* All objects (except for free Nodes and empty Triangles and Links) can be
* visited by the corresponding Iterator. Direct access is provided only for
* Nodes (needed to resolve Node indexed commonly used as reference). Triangles
* and Links can be retrieved by their index only internally, the public API
* provides only references or pointers to C++ objects. If you need a direct
* access to Triangles and Links, you can subclass Poly_CoherentTriangulation
* and use the protected API for your needs.
* <br>
* Memory management: All data objects are stored in NCollection_Vector
* containers that prove to be efficient for the performance. In addition
* references to triangles are stored in ring lists, with an instance of such
* list per Poly_CoherentNode. These lists are allocated in a memory allocator
* that is provided in the constructor of Poly_CoherentTriangulation. By default
* the standard OCCT allocator (aka NCollection_BaseAllocator) is used. But if
* you need to increase the performance you can use NCollection_IncAllocator
* instead.
* </ul>
*/
class Poly_CoherentTriangulation : public Standard_Transient
{
public:
/**
* Subclass Iterator - allows to iterate all triangles skipping those that
* have been removed.
*/
class IteratorOfTriangle : public Poly_BaseIteratorOfCoherentTriangle
{
public:
//! Constructor
Standard_EXPORT IteratorOfTriangle
(const Handle_Poly_CoherentTriangulation& theTri);
//! Make step
Standard_EXPORT virtual void Next ();
};
/**
* Subclass Iterator - allows to iterate all nodes skipping the free ones.
*/
class IteratorOfNode : public Poly_BaseIteratorOfCoherentNode
{
public:
//! Constructor
Standard_EXPORT IteratorOfNode
(const Handle_Poly_CoherentTriangulation& theTri);
//! Make step
Standard_EXPORT virtual void Next ();
};
/**
* Subclass Iterator - allows to iterate all links skipping invalid ones.
*/
class IteratorOfLink : public Poly_BaseIteratorOfCoherentLink
{
public:
//! Constructor
Standard_EXPORT IteratorOfLink
(const Handle_Poly_CoherentTriangulation& theTri);
//! Make step
Standard_EXPORT virtual void Next ();
};
//! Couple of integer indices (used in RemoveDegenerated()).
struct TwoIntegers
{
Standard_Integer myValue[2];
TwoIntegers() {}
TwoIntegers(Standard_Integer i0, Standard_Integer i1) {
myValue[0] = i0; myValue[1] = i1;
}
};
public:
// ---------- PUBLIC METHODS ----------
/**
* Empty constructor.
*/
Standard_EXPORT Poly_CoherentTriangulation
(const Handle_NCollection_BaseAllocator& theAlloc = 0L);
/**
* Constructor. It does not create Links, you should call ComputeLinks
* following this constructor if you need these links.
*/
Standard_EXPORT Poly_CoherentTriangulation
(const Handle_Poly_Triangulation& theTriangulation,
const Handle_NCollection_BaseAllocator& theAlloc = 0L);
/**
* Destructor.
*/
Standard_EXPORT virtual ~Poly_CoherentTriangulation ();
/**
* Create an instance of Poly_Triangulation from this object.
*/
Standard_EXPORT Handle_Poly_Triangulation
GetTriangulation () const;
/**
* Find and remove degenerated triangles in Triangulation.
* @param theTol
* Tolerance for the degeneration case. If any two nodes of a triangle have
* the distance less than this tolerance, this triangle is considered
* degenerated and therefore removed by this method.
* @param pLstRemovedNode
* Optional parameter. If defined, then it will receive the list of arrays
* where the first number is the index of removed node and the seond -
* the index of remaining node to which the mesh was reconnected.
*/
Standard_EXPORT Standard_Boolean RemoveDegenerated
(const Standard_Real theTol,
NCollection_List<TwoIntegers> * pLstRemovedNode = 0L);
/**
* Create a list of free nodes. These nodes may appear as a result of any
* custom mesh decimation or RemoveDegenerated() call. This analysis is
* necessary if you support additional data structures based on the
* triangulation (e.g., edges on the surface boundary).
* @param lstNodes
* <tt>[out]</tt> List that receives the indices of free nodes.
*/
Standard_EXPORT Standard_Boolean GetFreeNodes
(NCollection_List<Standard_Integer>& lstNodes) const;
/**
* Query the index of the last node in the triangulation
*/
inline Standard_Integer MaxNode () const
{ return myNodes.Length() - 1; }
/**
* Query the index of the last triangle in the triangulation
*/
inline Standard_Integer MaxTriangle () const
{ return myTriangles.Length() - 1; }
/**
* Set the Deflection value as the parameter of the given triangulation.
*/
inline void SetDeflection(const Standard_Real theDefl)
{ myDeflection = theDefl; }
/**
* Query the Deflection parameter (default value 0. -- if never initialized)
*/
inline Standard_Real Deflection () const
{ return myDeflection; }
/**
* Initialize a node
* @param thePoint
* 3D Coordinates of the node.
* @param iN
* Index of the node. If negative (default), the node is added to the
* end of the current array of nodes.
* @return
* Index of the added node.
*/
Standard_EXPORT Standard_Integer SetNode (const gp_XYZ& thePnt,
const Standard_Integer iN= -1);
/**
* Get the node at the given index 'i'.
*/
inline const Poly_CoherentNode& Node (const Standard_Integer i) const
{ return myNodes.Value(i); }
/**
* Get the node at the given index 'i'.
*/
inline Poly_CoherentNode& ChangeNode (const Standard_Integer i)
{ return myNodes.ChangeValue(i); }
/**
* Query the total number of active nodes (i.e. nodes used by 1 or more
* triangles)
*/
Standard_EXPORT Standard_Integer NNodes () const;
/**
* Get the triangle at the given index 'i'.
*/
inline const Poly_CoherentTriangle& Triangle (const Standard_Integer i) const
{ return myTriangles.Value(i); }
/**
* Query the total number of active triangles (i.e. triangles that refer
* nodes, non-empty ones)
*/
Standard_EXPORT Standard_Integer NTriangles () const;
/**
* Query the total number of active Links.
*/
Standard_EXPORT Standard_Integer NLinks () const;
/**
* Removal of a single triangle from the triangulation.
*/
Standard_EXPORT Standard_Boolean RemoveTriangle(Poly_CoherentTriangle& theTr);
/**
* Removal of a single link from the triangulation.
*/
Standard_EXPORT void RemoveLink (Poly_CoherentLink& theLink);
/**
* Add a triangle to the triangulation.
* @return
* Pointer to the added triangle instance or NULL if an error occurred.
*/
Standard_EXPORT Poly_CoherentTriangle *
AddTriangle (const Standard_Integer iNode0,
const Standard_Integer iNode1,
const Standard_Integer iNode2);
/**
* Replace nodes in the given triangle.
* @return
* True if operation succeeded.
*/
Standard_EXPORT Standard_Boolean ReplaceNodes
(Poly_CoherentTriangle& theTriangle,
const Standard_Integer iNode0,
const Standard_Integer iNode1,
const Standard_Integer iNode2);
/**
* Add a single link to triangulation, based on a triangle and its side index.
* This method does not check for coincidence with already present links.
* @param theTri
* Triangle that contains the link to be added.
* @param theConn
* Index of the side (i.e., 0, 1 0r 2) defining the added link.
*/
Standard_EXPORT Poly_CoherentLink *
AddLink (const Poly_CoherentTriangle& theTri,
const Standard_Integer theConn);
/**
* Find one or two triangles that share the given couple of nodes.
* @param theLink
* Link (in fact, just a couple of nodes) on which the triangle is
* searched.
* @param pTri
* <tt>[out]</tt> Array of two pointers to triangle. pTri[0] stores the
* triangle to the left of the link, while pTri[1] stores the one to the
* right of the link.
* @return
* True if at least one triangle is found and output as pTri.
*/
Standard_EXPORT Standard_Boolean FindTriangle
(const Poly_CoherentLink& theLink,
const Poly_CoherentTriangle* pTri[2]) const;
/**
* (Re)Calculate all links in this Triangulation.
*/
Standard_EXPORT Standard_Integer ComputeLinks ();
/**
* Clear all Links data from the Triangulation data.
*/
Standard_EXPORT void ClearLinks ();
/**
* Query the allocator of elements, this allocator can be used for other
* objects
*/
inline const Handle_NCollection_BaseAllocator&
Allocator () const
{
return myAlloc;
}
/**
* Create a copy of this Triangulation, using the given allocator.
*/
Standard_EXPORT Handle_Poly_CoherentTriangulation Clone
(const Handle_NCollection_BaseAllocator& theAlloc) const;
/**
* Debugging output.
*/
Standard_EXPORT void Dump (Standard_OStream&) const;
protected:
// ---------- PROTECTED METHODS ----------
protected:
// ---------- PROTECTED FIELDS ----------
NCollection_Vector<Poly_CoherentTriangle> myTriangles;
NCollection_Vector<Poly_CoherentNode> myNodes;
NCollection_Vector<Poly_CoherentLink> myLinks;
Handle_NCollection_BaseAllocator myAlloc;
Standard_Real myDeflection;
public:
// Declaration of CASCADE RTTI
DEFINE_STANDARD_RTTI (Poly_CoherentTriangulation)
friend class IteratorOfTriangle;
friend class IteratorOfNode;
friend class IteratorOfLink;
};
#include <Handle_Poly_CoherentTriangulation.hxx>
#endif

133
src/Poly/Poly_Connect.cdl Executable file
View File

@@ -0,0 +1,133 @@
-- File: Poly_Connect.cdl
-- Created: Mon Mar 6 15:16:16 1995
-- Author: Laurent PAINNOT
-- <lpa@metrox>
---Copyright: Matra Datavision 1995
class Connect from Poly
---Purpose:
-- Provides an algorithm to explore, inside a triangulation, the
-- adjacency data for a node or a triangle.
-- Adjacency data for a node consists of triangles which
-- contain the node.
-- Adjacency data for a triangle consists of:
-- - the 3 adjacent triangles which share an edge of the triangle,
-- - and the 3 nodes which are the other nodes of these adjacent triangles.
-- Example
-- Inside a triangulation, a triangle T
-- has nodes n1, n2 and n3.
-- It has adjacent triangles AT1, AT2 and AT3 where:
-- - AT1 shares the nodes n2 and n3,
-- - AT2 shares the nodes n3 and n1,
-- - AT3 shares the nodes n1 and n2.
-- It has adjacent nodes an1, an2 and an3 where:
-- - an1 is the third node of AT1,
-- - an2 is the third node of AT2,
-- - an3 is the third node of AT3.
-- So triangle AT1 is composed of nodes n2, n3 and an1.
-- There are two ways of using this algorithm.
-- - From a given node you can look for one triangle that
-- passes through the node, then look for the triangles
-- adjacent to this triangle, then the adjacent nodes. You
-- can thus explore the triangulation step by step (functions
-- Triangle, Triangles and Nodes).
-- - From a given node you can look for all the triangles
-- that pass through the node (iteration method, using the
-- functions Initialize, More, Next and Value).
-- A Connect object can be seen as a tool which analyzes a
-- triangulation and translates it into a series of triangles. By
-- doing this, it provides an interface with other tools and
-- applications working on basic triangles, and which do not
-- work directly with a Poly_Triangulation.
uses
Array1OfInteger from TColStd,
Triangulation from Poly
is
Create (T : Triangulation from Poly) returns Connect from Poly;
---Purpose: Constructs an algorithm to explore the adjacency data of
-- nodes or triangles for the triangulation T.
Triangulation(me) returns Triangulation from Poly;
---Purpose: Returns the triangulation analyzed by this tool.
---C++: inline
Triangle(me; N : Integer) returns Integer;
---Purpose: Returns the index of a triangle containing the node at
-- index N in the nodes table specific to the triangulation analyzed by this tool
---C++: inline
Triangles(me; T: Integer; t1, t2, t3: out Integer);
---Purpose: Returns in t1, t2 and t3, the indices of the 3 triangles
-- adjacent to the triangle at index T in the triangles table
-- specific to the triangulation analyzed by this tool.
-- Warning
-- Null indices are returned when there are fewer than 3
-- adjacent triangles.
Nodes(me; T: Integer; n1, n2, n3: out Integer);
---Purpose: Returns, in n1, n2 and n3, the indices of the 3 nodes
-- adjacent to the triangle referenced at index T in the
-- triangles table specific to the triangulation analyzed by this tool.
-- Warning
-- Null indices are returned when there are fewer than 3 adjacent nodes.
Initialize(me: in out; N: Integer);
---Purpose: Initializes an iterator to search for all the triangles
-- containing the node referenced at index N in the nodes
-- table, for the triangulation analyzed by this tool.
-- The iterator is managed by the following functions:
-- - More, which checks if there are still elements in the iterator
-- - Next, which positions the iterator on the next element
-- - Value, which returns the current element.
-- The use of such an iterator provides direct access to the
-- triangles around a particular node, i.e. it avoids iterating on
-- all the component triangles of a triangulation.
-- Example
-- Poly_Connect C(Tr);
-- for
-- (C.Initialize(n1);C.More();C.Next())
-- {
-- t = C.Value();
-- }
More(me) returns Boolean;
---Purpose: Returns true if there is another element in the iterator
-- defined with the function Initialize (i.e. if there is another
-- triangle containing the given node).
---C++: inline
Next(me: in out)
---Purpose: Advances the iterator defined with the function Initialize to
-- access the next triangle.
-- Note: There is no action if the iterator is empty (i.e. if the
-- function More returns false).-
is static;
Value(me) returns Integer;
---Purpose: Returns the index of the current triangle to which the
-- iterator, defined with the function Initialize, points. This is
-- an index in the triangles table specific to the triangulation
-- analyzed by this tool
fields
myTriangulation : Triangulation from Poly;
myTriangles : Array1OfInteger from TColStd;
myAdjacents : Array1OfInteger from TColStd;
mytr : Integer from Standard;
myfirst : Integer from Standard;
mynode : Integer from Standard;
myothernode : Integer from Standard;
mysense : Boolean from Standard;
mymore : Boolean from Standard;
end Connect;

280
src/Poly/Poly_Connect.cxx Executable file
View File

@@ -0,0 +1,280 @@
// File: Poly_Connect.cxx
// Created: Mon Mar 6 16:30:09 1995
// Author: Laurent PAINNOT
// <lpa@metrox>
#include <Poly_Connect.ixx>
#include <Poly_Triangle.hxx>
#include <Standard.hxx>
//=======================================================================
//function : Poly_Connect
//purpose :
//=======================================================================
// this structure records one of the edges starting from a node
//typedef struct polyedge {
struct polyedge {
polyedge* next; // the next edge in the list
Standard_Integer nd; // the second node of the edge
Standard_Integer nt[2]; // the two adjacent triangles
Standard_Integer nn[2]; // the two adjacent nodes
void* operator new(size_t aSize)
{return (void*)(Standard::Allocate(aSize));}
// void operator delete(void* aNode, size_t aSize) {
void operator delete(void* aNode) {
Standard_Address anAdress = (Standard_Address)aNode;
Standard::Free(anAdress);
}
};
Poly_Connect::Poly_Connect(const Handle(Poly_Triangulation)& T) :
myTriangulation(T),
myTriangles(1,T->NbNodes()),
myAdjacents(1,6*T->NbTriangles())
{
myTriangles.Init(0);
myAdjacents.Init(0);
Standard_Integer nbNodes = myTriangulation->NbNodes();
Standard_Integer nbTriangles = myTriangulation->NbTriangles();
// We first build an array of the list of edges connected to the nodes
// create an array to store the edges starting from the vertices
Standard_Integer i;
// the last node is not used because edges are stored at the lower node index
polyedge** edges = new polyedge*[nbNodes];
for (i = 0; i < nbNodes; i++) edges[i] = 0;
// loop on the triangles
Standard_Integer j,k,n[3],n1,n2;
const Poly_Array1OfTriangle& triangles = myTriangulation->Triangles();
for (i = 1; i <= nbTriangles; i++) {
// get the nodes
triangles(i).Get(n[0],n[1],n[2]);
// Update the myTriangles array
myTriangles(n[0]) = i;
myTriangles(n[1]) = i;
myTriangles(n[2]) = i;
// update the edge lists
for (j = 0; j < 3; j++) {
k = (j+1) % 3; // the following node of the edge
if (n[j] <= n[k]) {
n1 = n[j];
n2 = n[k];
}
else {
n1 = n[k];
n2 = n[j];
}
// edge from n1 to n2 with n1 < n2
// insert in the list of n1
polyedge* ced = edges[n1];
while (ced != 0) {
// the edge already exists
if (ced->nd == n2)
break;
else
ced = ced->next;
}
if (ced == 0) {
// create the edge if not found
ced = new polyedge;
ced->next = edges[n1];
edges[n1] = ced;
ced->nd = n2;
ced->nt[0] = i;
ced->nn[0] = n[3-j-k]; // the third node
ced->nt[1] = 0;
ced->nn[1] = 0;
}
else {
// just mark the adjacency if found
ced->nt[1] = i;
ced->nn[1] = n[3-j-k]; // the third node
}
}
}
// now complete the myAdjacents array
Standard_Integer index = 1;
for (i = 1; i <= nbTriangles; i++) {
// get the nodes
triangles(i).Get(n[0],n[1],n[2]);
// fore each edge
for (j = 0; j < 3; j++) {
k = (j+1) % 3; // the following node of the edge
if (n[j] <= n[k]) {
n1 = n[j];
n2 = n[k];
}
else {
n1 = n[k];
n2 = n[j];
}
// edge from n1 to n2 with n1 < n2
// find in the list of n1
polyedge* ced = edges[n1];
while (ced->nd != n2)
ced = ced->next;
// Find the adjacent triangle
Standard_Integer l = 0;
if (ced->nt[0] == i) l = 1;
myAdjacents(index) = ced->nt[l];
myAdjacents(index+3) = ced->nn[l];
index++;
}
index += 3;
}
// destroy the edges array
for (i = 0; i < nbNodes; i++) {
polyedge* ced = edges[i];
while (ced != 0) {
polyedge* tmp = ced->next;
delete ced;
ced = tmp;
}
}
delete [] edges;
}
//=======================================================================
//function : Triangles
//purpose :
//=======================================================================
void Poly_Connect::Triangles(const Standard_Integer T,
Standard_Integer& t1,
Standard_Integer& t2,
Standard_Integer& t3) const
{
Standard_Integer index = 6*(T-1);
t1 = myAdjacents(index+1);
t2 = myAdjacents(index+2);
t3 = myAdjacents(index+3);
}
//=======================================================================
//function : Nodes
//purpose :
//=======================================================================
void Poly_Connect::Nodes(const Standard_Integer T,
Standard_Integer& n1,
Standard_Integer& n2,
Standard_Integer& n3) const
{
Standard_Integer index = 6*(T-1);
n1 = myAdjacents(index+4);
n2 = myAdjacents(index+5);
n3 = myAdjacents(index+6);
}
//=======================================================================
//function : Initialize
//purpose :
//=======================================================================
void Poly_Connect::Initialize(const Standard_Integer N)
{
mynode = N;
myfirst = Triangle(N);
mytr = myfirst;
Standard_Integer i, no[3];
const Poly_Array1OfTriangle& triangles = myTriangulation->Triangles();
triangles(myfirst).Get(no[0], no[1], no[2]);
for (i = 0; i < 3; i++)
if (no[i] == mynode) break;
myothernode = no[(i+2)%3];
mysense = Standard_True;
mymore = Standard_True;
}
//=======================================================================
//function : Next
//purpose :
//=======================================================================
void Poly_Connect::Next()
{
Standard_Integer i, j;
static Standard_Integer n[3];
static Standard_Integer t[3];
const Poly_Array1OfTriangle& triangles = myTriangulation->Triangles();
Triangles(mytr, t[0], t[1], t[2]);
if (mysense) {
for (i = 0; i < 3; i++) {
if (t[i] != 0) {
triangles(t[i]).Get(n[0], n[1], n[2]);
for (j = 0; j < 3; j++) {
if ((n[j] == mynode) && (n[(j+1)%3] == myothernode)) {
mytr = t[i];
myothernode = n[(j+2)%3];
mymore = (mytr != myfirst);
return;
}
}
}
}
// sinon, depart vers la gauche.
triangles(myfirst).Get(n[0], n[1], n[2]);
for (i = 0; i < 3; i++)
if (n[i] == mynode) break;
myothernode = n[(i+1)%3];
mysense = Standard_False;
mytr = myfirst;
Triangles(mytr, t[0], t[1], t[2]);
}
if (!mysense) {
for (i = 0; i < 3; i++) {
if (t[i] != 0) {
triangles(t[i]).Get(n[0], n[1], n[2]);
for (j = 0; j < 3; j++) {
if ((n[j] == mynode) && (n[(j+2)%3] == myothernode)) {
mytr = t[i];
myothernode = n[(j+1)%3];
mymore = Standard_True;
return;
}
}
}
}
}
mymore = Standard_False;
}
//=======================================================================
//function : Value
//purpose :
//=======================================================================
Standard_Integer Poly_Connect::Value() const
{
return mytr;
}

34
src/Poly/Poly_Connect.lxx Executable file
View File

@@ -0,0 +1,34 @@
// File: Poly_Connect.lxx
// Created: Mon Mar 6 16:25:53 1995
// Author: Laurent PAINNOT
// <lpa@metrox>
//=======================================================================
//function : Triangulation
//purpose :
//=======================================================================
inline Handle(Poly_Triangulation) Poly_Connect::Triangulation() const
{
return myTriangulation;
}
//=======================================================================
//function : Triangle
//purpose :
//=======================================================================
inline Standard_Integer Poly_Connect::Triangle(const Standard_Integer N) const
{
return myTriangles(N);
}
//=======================================================================
//function : More
//purpose :
//=======================================================================
inline Standard_Boolean Poly_Connect::More() const
{
return (mymore);
}

View File

@@ -0,0 +1,19 @@
// File: Poly_ListOfTriangulation.hxx
// Created: 21.04.08 11:12
// Author: Alexander GRIGORIEV
// Copyright: Open Cascade 2008
#ifndef Poly_ListOfTriangulation_HeaderFile
#define Poly_ListOfTriangulation_HeaderFile
#include <NCollection_List.hxx>
#include <Handle_Poly_Triangulation.hxx>
/**
* List of Poly_Triangulation instances.
*/
typedef NCollection_List<Handle_Poly_Triangulation> Poly_ListOfTriangulation;
#endif

694
src/Poly/Poly_MakeLoops.cxx Executable file
View File

@@ -0,0 +1,694 @@
// File: Poly_MakeLoops.cxx
// Created: 22.10.2009
// Author: Mikhail SAZONOV
// Copyright: Open Cascade 2009
#include <Poly_MakeLoops.hxx>
#include <NCollection_IncAllocator.hxx>
#include <NCollection_DataMap.hxx>
#include <gp_Dir.hxx>
#include <gp_Dir2d.hxx>
#ifdef _DEBUG
static Standard_Integer doDebug = 0;
#endif
//=======================================================================
//function : Poly_MakeLoops
//purpose :
//=======================================================================
Poly_MakeLoops::Poly_MakeLoops(const Helper* theHelper,
const Handle_NCollection_BaseAllocator& theAlloc)
: myHelper (theHelper),
myAlloc (theAlloc),
myMapLink (4000, myAlloc),
myLoops (myAlloc),
myStartIndices (4000)
{
}
//=======================================================================
//function : Reset
//purpose :
//=======================================================================
void Poly_MakeLoops::Reset
(const Helper* theHelper,
const Handle_NCollection_BaseAllocator& theAlloc)
{
myHelper = theHelper;
myMapLink.Clear();
myLoops.Clear(theAlloc);
myStartIndices.Clear();
myAlloc = theAlloc;
}
//=======================================================================
//function : AddLink
//purpose :
//=======================================================================
void Poly_MakeLoops::AddLink(const Link& theLink)
{
if (theLink.node1 == theLink.node2)
return;
Standard_Integer aInd = myMapLink.Add(theLink);
Link& aLink = const_cast<Link&>(myMapLink(aInd));
aLink.flags |= theLink.flags;
#ifdef _DEBUG
myHelper->OnAddLink (aInd, aLink);
#endif
}
//=======================================================================
//function : ReplaceLink
//purpose :
//=======================================================================
void Poly_MakeLoops::ReplaceLink(const Link& theLink, const Link& theNewLink)
{
if (theNewLink.node1 == theNewLink.node2)
return;
Standard_Integer aInd = myMapLink.Add(theLink);
if (aInd > 0)
{
Link aLink;
// replace with a null link first (workaround exception)
myMapLink.Substitute(aInd, aLink);
aLink = theNewLink;
// and now put there the final value of link
myMapLink.Substitute(aInd, aLink);
#ifdef _DEBUG
myHelper->OnAddLink (aInd, aLink);
#endif
}
}
//=======================================================================
//function : SetLinkOrientation
//purpose :
//=======================================================================
Poly_MakeLoops::LinkFlag Poly_MakeLoops::SetLinkOrientation
(const Link& theLink,
const LinkFlag theOrient)
{
Standard_Integer aInd = myMapLink.FindIndex(theLink);
LinkFlag aOri = LF_None;
if (aInd > 0)
{
Link& aLink = const_cast<Link&>(myMapLink(aInd));
aOri = (LinkFlag) (aLink.flags & LF_Both);
aLink.flags = theOrient;
#ifdef _DEBUG
myHelper->OnAddLink (aInd, aLink);
#endif
}
return aOri;
}
//=======================================================================
//function : FindLink
//purpose :
//=======================================================================
Poly_MakeLoops::Link Poly_MakeLoops::FindLink(const Link& theLink) const
{
Standard_Integer aInd = myMapLink.FindIndex(theLink);
Poly_MakeLoops::Link aLink;
if (aInd > 0)
aLink = myMapLink(aInd);
return aLink;
}
//=======================================================================
//function : Perform
//purpose :
//=======================================================================
Standard_Integer Poly_MakeLoops::Perform()
{
// prepare the set of start indices
myStartIndices.Clear();
Standard_Integer i;
for (i = 1; i <= myMapLink.Extent(); i++)
{
const Link& aLink = myMapLink(i);
if (aLink.flags & LF_Fwd)
myStartIndices.Add(i);
if (aLink.flags & LF_Rev)
myStartIndices.Add(-i);
}
#ifdef _DEBUG
if (doDebug)
showBoundaryBreaks();
#endif
Standard_Integer aResult = 0;
Handle(NCollection_IncAllocator) aTempAlloc = new NCollection_IncAllocator(4000);
Handle(NCollection_IncAllocator) aTempAlloc1 = new NCollection_IncAllocator(4000);
// two pass loop
Standard_Integer aPassNum, nbLoopsOnPass2 = 0;
for (aPassNum=0; aPassNum < 2; aPassNum++)
{
myHangIndices.Clear();
// main loop
while (!myStartIndices.IsEmpty())
{
Standard_Integer aIndexS = myStartIndices.Top();
aTempAlloc->Reset();
NCollection_IndexedMap<Standard_Integer> aContour (100, aTempAlloc);
Standard_Integer aStartNumber = findContour (aIndexS, aContour, aTempAlloc, aTempAlloc1);
#ifdef _DEBUG
if (aStartNumber > 1)
if (doDebug)
{
cout << "--- found contour with hanging links:" << endl;
for (i = 1; i <= aContour.Extent(); i++)
cout << " " << aContour(i);
cout << endl;
}
#endif
if (aStartNumber == 0)
{ // error
aResult |= RC_Failure;
return aResult;
}
if (aStartNumber <= aContour.Extent())
{
// there is a closed loop in the contour
if (aPassNum == 1)
nbLoopsOnPass2++;
acceptContour (aContour, aStartNumber);
}
if (aStartNumber > 1)
{
// it is required to mark hanging edges
Standard_Integer aNode;
if (aStartNumber <= aContour.Extent())
// mark hanging edges starting from the first one till a bifurcation
aNode = getFirstNode(aIndexS);
else
{
// open contour - mark from the end back till a bifurcation
aIndexS = aContour(aStartNumber - 1);
aNode = getLastNode(aIndexS);
}
markHangChain(aNode, aIndexS);
}
}
if (aPassNum == 0)
{
// move hanging links to start indices to make the second pass
TColStd_MapIteratorOfPackedMapOfInteger it(myHangIndices);
for (; it.More(); it.Next())
myStartIndices.Add(it.Key());
}
}
#ifdef _DEBUG
if (doDebug && nbLoopsOnPass2)
cout << "MakeLoops: " << nbLoopsOnPass2
<< " contours accepted on the second pass" << endl;
#endif
if (!myLoops.IsEmpty())
aResult |= RC_LoopsDone;
if (!myHangIndices.IsEmpty())
aResult |= RC_HangingLinks;
return aResult;
}
//=======================================================================
//function : findContour
//purpose : Collects edges in chain until they form a closed contour.
// Returns the index in the map theContour where the loop starts.
// It may return the number greater than the extent of the map by 1,
// what means that the contour is open
//=======================================================================
Standard_Integer Poly_MakeLoops::findContour
(Standard_Integer theIndexS,
NCollection_IndexedMap<Standard_Integer> &theContour,
const Handle_NCollection_BaseAllocator& theTempAlloc,
const Handle_NCollection_IncAllocator& theTempAlloc1) const
{
theContour.Clear();
Standard_Integer aStartIndex = 0;
Standard_Integer aIndexS = theIndexS;
NCollection_DataMap<Standard_Integer,Standard_Integer> aNodeLink(100, theTempAlloc);
Standard_Integer aLastNode = getLastNode (aIndexS);
for (;;) {
theContour.Add(aIndexS);
aNodeLink.Bind(getFirstNode(aIndexS), aIndexS);
Standard_Integer aIndex = Abs (aIndexS);
// collect the list of links from this node able to participate
// in this contour
theTempAlloc1->Reset();
NCollection_List<Standard_Integer> aLstIndS (theTempAlloc1);
const ListOfLink& aLinks = myHelper->GetAdjacentLinks (aLastNode);
Poly_MakeLoops::ListOfLink::Iterator itLinks (aLinks);
for (; itLinks.More(); itLinks.Next()) {
Standard_Integer aInd = myMapLink.FindIndex(itLinks.Value());
if (aInd == 0 || aInd == aIndex)
continue;
// determine the orientation in which the link is to be taken
Standard_Integer aIndS = aInd;
Standard_Integer aNode1 = getFirstNode(aInd);
if (aNode1 != aLastNode)
aIndS = -aIndS;
if (canLinkBeTaken(aIndS))
aLstIndS.Append(aIndS);
}
if (aLstIndS.IsEmpty()) {
// no more ways: open contour
aStartIndex = theContour.Extent() + 1;
break;
}
Standard_Integer aIndexSNext = 0;
if (aLstIndS.First() == aLstIndS.Last())
// only one possible way
aIndexSNext = aLstIndS.First();
else
// find the most left way
aIndexSNext = chooseLeftWay (aLastNode, aIndexS, aLstIndS);
aIndexS = aIndexSNext;
if (aIndexS == 0)
{
// no more ways: open contour
aStartIndex = theContour.Extent() + 1;
break;
}
if (theContour.Contains(aIndexS))
{
// entering the loop second time, stop search
aStartIndex = theContour.FindIndex (aIndexS);
break;
}
if (theContour.Contains (-aIndexS))
{
// leaving the loop, stop search
aStartIndex = theContour.FindIndex (-aIndexS) + 1;
break;
}
aLastNode = getLastNode (aIndexS);
if (aNodeLink.IsBound(aLastNode))
{
// closing the loop, stop search
theContour.Add(aIndexS);
aStartIndex = theContour.FindIndex(aNodeLink.Find(aLastNode));
break;
}
}
return aStartIndex;
}
//=======================================================================
//function : acceptContour
//purpose : Builds a wire from a given set of edge indices (starting with
// theStartNumber) and appends it to the result list.
// Also updates the start indices.
//=======================================================================
void Poly_MakeLoops::acceptContour
(const NCollection_IndexedMap<Standard_Integer>& theContour,
Standard_Integer theStartNumber)
{
// append a new loop to the result
Loop anEmptyLoop(myAlloc);
myLoops.Append(anEmptyLoop);
Loop& aLoop = myLoops.ChangeValue(myLoops.Length());
// build a loop, mark links as taken,
// remove them from the set of start indices
Standard_Integer i;
for (i = theStartNumber; i <= theContour.Extent(); i++)
{
Standard_Integer aIndexS = theContour(i); // index with sign
Standard_Integer aIndex = Abs (aIndexS);
const Link& aLink = myMapLink(aIndex);
Link aOrientedLink = aLink;
if (aIndexS < 0)
aOrientedLink.Reverse();
aLoop.Append(aOrientedLink);
// remove from start set
myStartIndices.Remove(aIndexS);
}
}
//=======================================================================
//function : getFirstNode
//purpose : Returns the first node of the given link
// taking into account its orientation (the sign of index)
//=======================================================================
Standard_Integer Poly_MakeLoops::getFirstNode(Standard_Integer theIndexS) const
{
Standard_Integer aIndex = Abs(theIndexS);
const Link& aLink = myMapLink(aIndex);
if (theIndexS > 0)
return aLink.node1;
return aLink.node2;
}
//=======================================================================
//function : getLastNode
//purpose : Returns the last node of the given link
// taking into account its orientation (the sign of index)
//=======================================================================
Standard_Integer Poly_MakeLoops::getLastNode(int theIndexS) const
{
Standard_Integer aIndex = Abs(theIndexS);
const Link& aLink = myMapLink(aIndex);
if (theIndexS > 0)
return aLink.node2;
return aLink.node1;
}
//=======================================================================
//function : markHangChain
//purpose : Marks hanging links starting from the given node.
// Also removes such links from the start indices.
//=======================================================================
void Poly_MakeLoops::markHangChain(Standard_Integer theNode, Standard_Integer theIndexS)
{
Standard_Integer aNode1 = theNode;
Standard_Integer aIndexS = theIndexS;
Standard_Integer aIndex = Abs(aIndexS);
Standard_Boolean isOut = (aNode1 == getFirstNode(aIndexS));
for (;;)
{
// check if the current link is hanging:
// if it is outcoming from aNode1 then count the number of
// other incoming links and vise versa;
// if the number is zero than it is hanging
const ListOfLink& aLinks = myHelper->GetAdjacentLinks (aNode1);
Standard_Integer nEdges = 0;
Poly_MakeLoops::ListOfLink::Iterator itLinks (aLinks);
for (; itLinks.More() && nEdges == 0; itLinks.Next())
{
const Link &aL = itLinks.Value();
Standard_Integer aInd = myMapLink.FindIndex(aL);
if (aInd == 0 || aInd == aIndex)
continue;
if (isOut && aNode1 == aL.node1 ||
!isOut && aNode1 == aL.node2)
aInd = -aInd;
if (canLinkBeTaken(aInd))
nEdges++;
}
if (nEdges > 0)
// leave this chain
break;
// mark the current link as hanging
myStartIndices.Remove(aIndexS);
myHangIndices.Add(aIndexS);
// get other node of the link and the next link
if (isOut)
aNode1 = getLastNode(aIndexS);
else
aNode1 = getFirstNode(aIndexS);
const ListOfLink& aNextLinks = myHelper->GetAdjacentLinks (aNode1);
Standard_Integer aNextIndexS = 0;
for (itLinks.Init(aNextLinks); itLinks.More(); itLinks.Next())
{
const Link &aL = itLinks.Value();
Standard_Integer aInd = myMapLink.FindIndex(aL);
if (aInd == 0 || aInd == aIndex)
continue;
if (isOut && aNode1 == aL.node2 ||
!isOut && aNode1 == aL.node1)
aInd = -aInd;
if (canLinkBeTaken(aInd))
{
if (aNextIndexS == 0)
aNextIndexS = aInd;
else
{
// more than 1 ways, stop the chain
aNextIndexS = 0;
break;
}
}
}
if (aNextIndexS == 0)
break;
aIndexS = aNextIndexS;
aIndex = Abs(aIndexS);
}
}
//=======================================================================
//function : canLinkBeTaken
//purpose : Returns True if the link appointed by the index can participate
// in a loop in given orientation (it is the sign of index).
// Remark: A boundary edge can be taken only once
//=======================================================================
Standard_Boolean Poly_MakeLoops::canLinkBeTaken(Standard_Integer theIndexS) const
{
return myStartIndices.Contains(theIndexS);
}
//=======================================================================
//function : showBoundaryBreaks
//purpose :
//=======================================================================
#ifdef _DEBUG
void Poly_MakeLoops::showBoundaryBreaks() const
{
// collect nodes of boundary links
TColStd_PackedMapOfInteger aNodesMap;
Standard_Integer i;
for (i = 1; i <= myMapLink.Extent(); i++)
{
const Link& aLink = myMapLink(i);
Standard_Integer aFlags = aLink.flags & LF_Both;
if (aFlags && aFlags != LF_Both)
{
// take only oriented links
aNodesMap.Add(aLink.node1);
aNodesMap.Add(aLink.node2);
}
}
// check each node if the number of input and output links are equal
Standard_Boolean isFirst = Standard_True;
TColStd_MapIteratorOfPackedMapOfInteger it(aNodesMap);
for (; it.More(); it.Next())
{
Standard_Integer aNode = it.Key();
Standard_Integer nb = 0;
const ListOfLink& aLinks = myHelper->GetAdjacentLinks(aNode);
Poly_MakeLoops::ListOfLink::Iterator itLinks (aLinks);
for (; itLinks.More(); itLinks.Next())
{
const Poly_MakeLoops::Link& aLink = itLinks.Value();
if (myMapLink.FindIndex(aLink) == 0)
continue;
Standard_Integer aFlags = aLink.flags & LF_Both;
if (aFlags && aFlags != LF_Both)
{
if (aNode == aLink.node1) // output?
{
if (aFlags & LF_Fwd)
nb++; // yes, output
else
nb--; // reversed, so input
}
else if (aNode == aLink.node2) // input?
{
if (aFlags & LF_Fwd)
nb--; // yes, input
else
nb++; // reversed, so output
}
else
// inconsistent
nb += 100;
}
}
if (nb != 0)
{
// indicate this node
if (isFirst)
{
isFirst = Standard_False;
cout << "boundary breaks are found in the following nodes:" << endl;
}
cout << aNode << " ";
}
}
if (!isFirst)
cout << endl;
}
#endif
//=======================================================================
//function : GetHangingLinks
//purpose :
//=======================================================================
void Poly_MakeLoops::GetHangingLinks(ListOfLink& theLinks) const
{
TColStd_MapIteratorOfPackedMapOfInteger it(myHangIndices);
for (; it.More(); it.Next())
{
Standard_Integer aIndexS = it.Key();
Link aLink = myMapLink(Abs(aIndexS));
if (aIndexS < 0)
aLink.Reverse();
theLinks.Append(aLink);
}
}
//=======================================================================
//function : Poly_MakeLoops3D
//purpose :
//=======================================================================
Poly_MakeLoops3D::Poly_MakeLoops3D(const Helper* theHelper,
const Handle_NCollection_BaseAllocator& theAlloc)
: Poly_MakeLoops (theHelper, theAlloc)
{
}
//=======================================================================
//function : Poly_MakeLoops3D::chooseLeftWay
//purpose :
//=======================================================================
Standard_Integer Poly_MakeLoops3D::chooseLeftWay
(const Standard_Integer theNode,
const Standard_Integer theSegIndex,
const NCollection_List<Standard_Integer>& theLstIndS) const
{
Standard_Real aAngleMin = ::PI * 2;
gp_Dir aNormal;
const Helper* aHelper = getHelper();
if (!aHelper->GetNormal (theNode, aNormal))
return theLstIndS.First();
Link aLink = getLink(theSegIndex);
gp_Dir aTgtRef;
if (!aHelper->GetLastTangent (aLink, aTgtRef))
return theLstIndS.First();
// project tangent vector to the plane orthogonal to normal
// to get the reference direction
gp_XYZ aTgtRefXYZ = aNormal.XYZ().CrossCrossed (aTgtRef.XYZ(), aNormal.XYZ());
if (aTgtRefXYZ.SquareModulus() < 1e-14)
// a problem with defining reference direction, take first way
return theLstIndS.First();
aTgtRef = aTgtRefXYZ;
// find the way with minimal angle to the reference direction
// (the angle is in range ]-PI;PI])
Standard_Integer aResIndex = 0;
NCollection_List<Standard_Integer>::Iterator aItI (theLstIndS);
for (; aItI.More(); aItI.Next())
{
Standard_Integer aIndS = aItI.Value();
aLink = getLink(aIndS);
gp_Dir aTgt;
if (!aHelper->GetFirstTangent (aLink, aTgt))
continue;
gp_XYZ aTgtXYZ = aNormal.XYZ().CrossCrossed (aTgt.XYZ(), aNormal.XYZ());
if (aTgtXYZ.SquareModulus() < 1e-14)
// skip a problem way
continue;
aTgt = aTgtXYZ;
Standard_Real aAngle = aTgt.AngleWithRef(aTgtRef, aNormal);
if (aAngle < 1e-4 - ::PI)
aAngle = ::PI;
if (aAngle < aAngleMin)
{
aAngleMin = aAngle;
aResIndex = aIndS;
}
}
return aResIndex == 0 ? theLstIndS.First() : aResIndex;
}
//=======================================================================
//function : Poly_MakeLoops2D
//purpose :
//=======================================================================
Poly_MakeLoops2D::Poly_MakeLoops2D(const Standard_Boolean theLeftWay,
const Helper* theHelper,
const Handle_NCollection_BaseAllocator& theAlloc)
: Poly_MakeLoops (theHelper, theAlloc),
myRightWay(!theLeftWay)
{
}
//=======================================================================
//function : Poly_MakeLoops2D::chooseLeftWay
//purpose :
//=======================================================================
Standard_Integer Poly_MakeLoops2D::chooseLeftWay
(const Standard_Integer /*theNode*/,
const Standard_Integer theSegIndex,
const NCollection_List<Standard_Integer>& theLstIndS) const
{
Standard_Real aAngleMin = ::PI * 2;
const Helper* aHelper = getHelper();
Link aLink = getLink(theSegIndex);
gp_Dir2d aTgtRef;
if (!aHelper->GetLastTangent (aLink, aTgtRef))
// a problem with defining reference direction, take first way
return theLstIndS.First();
// find the way with minimal angle to the reference direction
// (the angle is in range ]-PI;PI])
Standard_Integer aResIndex = 0;
NCollection_List<Standard_Integer>::Iterator aItI (theLstIndS);
for (; aItI.More(); aItI.Next())
{
Standard_Integer aIndS = aItI.Value();
aLink = getLink(aIndS);
gp_Dir2d aTgt;
if (!aHelper->GetFirstTangent (aLink, aTgt))
// skip a problem way
continue;
Standard_Real aAngle = aTgt.Angle(aTgtRef);
if (myRightWay)
aAngle = -aAngle;
if (aAngle < 1e-4 - ::PI)
aAngle = ::PI;
if (aAngle < aAngleMin)
{
aAngleMin = aAngle;
aResIndex = aIndS;
}
}
return aResIndex == 0 ? theLstIndS.First() : aResIndex;
}

354
src/Poly/Poly_MakeLoops.hxx Executable file
View File

@@ -0,0 +1,354 @@
// File: Poly_MakeLoops.hxx
// Created: 22.10.2009
// Author: Mikhail SAZONOV
// Copyright: Open Cascade 2009
#ifndef Poly_MakeLoops_HeaderFile
#define Poly_MakeLoops_HeaderFile
#include <NCollection_Sequence.hxx>
#include <NCollection_IndexedMap.hxx>
#include <TColStd_PackedMapOfInteger.hxx>
#include <TColStd_MapIteratorOfPackedMapOfInteger.hxx>
#include <NCollection_BaseAllocator.hxx>
#include <NCollection_List.hxx>
class Handle_NCollection_IncAllocator;
/**
* Make loops from a set of connected links. A link is represented by
* a pair of integer indices of nodes.
*/
class Poly_MakeLoops
{
public:
//! Orientation flags that can be attached to a link
enum LinkFlag {
LF_None = 0,
LF_Fwd = 1, // forward orientation
LF_Rev = 2, // reversed orientation
LF_Both = 3, // both ways oriented
LF_Reversed = 4 // means the link is reversed
};
//! The Link structure
struct Link
{
Standard_Integer node1, node2;
Standard_Integer flags;
Link()
: node1(0), node2(0), flags(0) {}
Link(Standard_Integer theNode1, Standard_Integer theNode2)
: node1(theNode1), node2(theNode2), flags(0) {}
void Reverse()
{
flags ^= Poly_MakeLoops::LF_Reversed;
}
Standard_Boolean IsReversed() const
{
return flags & Poly_MakeLoops::LF_Reversed;
}
void Nullify()
{
node1 = node2 = 0;
}
Standard_Boolean IsNull() const
{
return node1 == 0 || node2 == 0;
}
};
// Define the Loop as a list of links
typedef NCollection_List<Link> ListOfLink;
typedef ListOfLink Loop;
//! The abstract helper class
class Helper
{
public:
//! returns the links adjacent to the given node
virtual const ListOfLink& GetAdjacentLinks (Standard_Integer theNode) const = 0;
//! hook function called from AddLink in _DEBUG mode
virtual void OnAddLink (Standard_Integer /*theNum*/, const Link& /*theLink*/) const {}
};
//! This class implements a heap of integers. The most effective usage
//! of it is first to add there all items, and then get top item and remove
//! any items till it becomes empty.
class HeapOfInteger
{
public:
HeapOfInteger (const Standard_Integer theNbPreAllocated = 1)
: myMap (theNbPreAllocated),
myIterReady (Standard_False) {}
void Clear()
{
myMap.Clear();
myIterReady = Standard_False;
}
void Add (const Standard_Integer theValue)
{
myMap.Add (theValue);
myIterReady = Standard_False;
}
Standard_Integer Top()
{
if (!myIterReady)
{
myIter.Initialize (myMap);
myIterReady = Standard_True;
}
return myIter.Key();
}
Standard_Boolean Contains (const Standard_Integer theValue) const
{
return myMap.Contains (theValue);
}
void Remove (const Standard_Integer theValue)
{
if (myIterReady && myIter.More() && myIter.Key() == theValue)
myIter.Next();
myMap.Remove (theValue);
}
Standard_Boolean IsEmpty()
{
if (!myIterReady)
{
myIter.Initialize (myMap);
myIterReady = Standard_True;
}
return !myIter.More();
}
private:
TColStd_PackedMapOfInteger myMap;
TColStd_MapIteratorOfPackedMapOfInteger myIter;
Standard_Boolean myIterReady;
};
public:
// PUBLIC METHODS
//! Constructor. If helper is NULL then the algorithm will
//! probably return a wrong result
Standard_EXPORT Poly_MakeLoops(const Helper* theHelper,
const Handle_NCollection_BaseAllocator& theAlloc = 0L);
//! It is to reset the algorithm to the initial state.
Standard_EXPORT void Reset
(const Helper* theHelper,
const Handle_NCollection_BaseAllocator& theAlloc = 0L);
//! Adds a link to the set. theOrient defines which orientations of the link
//! are allowed.
Standard_EXPORT void AddLink(const Link& theLink);
//! Replace one link with another (e.g. to change order of nodes)
Standard_EXPORT void ReplaceLink(const Link& theLink, const Link& theNewLink);
//! Set a new value of orientation of a link already added earlier.
//! It can be used with LF_None to exclude the link from consideration.
//! Returns the old value of orienation.
Standard_EXPORT LinkFlag SetLinkOrientation
(const Link& theLink,
const LinkFlag theOrient);
//! Find the link stored in algo by value
Standard_EXPORT Link FindLink(const Link& theLink) const;
enum ResultCode
{
RC_LoopsDone = 1,
RC_HangingLinks = 2,
RC_Failure = 4
};
//! Does the work. Returns the collection of result codes
Standard_EXPORT Standard_Integer Perform();
//! Returns the number of loops in the result
Standard_Integer GetNbLoops() const
{
return myLoops.Length();
}
//! Returns the loop of the given index
const Loop& GetLoop(Standard_Integer theIndex) const
{
return myLoops.Value(theIndex);
}
//! Returns the number of detected hanging chains
Standard_Integer GetNbHanging() const
{
return myHangIndices.Extent();
}
//! Fills in the list of hanging links
void GetHangingLinks(ListOfLink& theLinks) const;
protected:
virtual Standard_Integer chooseLeftWay
(const Standard_Integer theNode,
const Standard_Integer theSegIndex,
const NCollection_List<Standard_Integer>& theLstIndS) const = 0;
const Helper* getHelper () const
{
return myHelper;
}
Link getLink (const Standard_Integer theSegIndex) const
{
Link aLink = myMapLink(Abs(theSegIndex));
if (theSegIndex < 0)
aLink.Reverse();
return aLink;
}
#ifdef _DEBUG
void showBoundaryBreaks() const;
#endif
private:
int findContour(Standard_Integer theIndexS, NCollection_IndexedMap<Standard_Integer>& theContour,
const Handle_NCollection_BaseAllocator& theTempAlloc,
const Handle_NCollection_IncAllocator& theTempAlloc1) const;
void acceptContour(const NCollection_IndexedMap<Standard_Integer>& theContour,
Standard_Integer theStartNumber);
Standard_Integer getFirstNode(Standard_Integer theIndexS) const;
Standard_Integer getLastNode(Standard_Integer theIndexS) const;
void markHangChain(Standard_Integer theNode, Standard_Integer theIndexS);
Standard_Boolean canLinkBeTaken(Standard_Integer theIndexS) const;
// FIELDS
const Helper* myHelper;
Handle_NCollection_BaseAllocator myAlloc;
NCollection_IndexedMap<Link> myMapLink;
NCollection_Sequence<Loop> myLoops;
HeapOfInteger myStartIndices;
TColStd_PackedMapOfInteger myHangIndices;
};
/**
* HashCode method is needed for maps
*/
inline Standard_Integer HashCode(const Poly_MakeLoops::Link& theKey,
int theLimit)
{
return HashCode(theKey.node1 + theKey.node2, theLimit);
}
/**
* IsEqual method is needed for maps
*/
inline Standard_Boolean IsEqual(const Poly_MakeLoops::Link& theKey1,
const Poly_MakeLoops::Link& theKey2)
{
return (theKey1.node1 == theKey2.node1 &&
theKey1.node2 == theKey2.node2 ||
theKey1.node1 == theKey2.node2 &&
theKey1.node2 == theKey2.node1);
}
/**
* Implementation for 3D space
*/
class gp_Dir;
class Poly_MakeLoops3D: public Poly_MakeLoops
{
public:
//! The abstract helper class
class Helper: public Poly_MakeLoops::Helper
{
public:
// all the following methods should return False if
// it is impossible to return a valid direction
//! returns the tangent vector at the first node of a link
virtual Standard_Boolean GetFirstTangent(const Link& theLink,
gp_Dir& theDir) const = 0;
//! returns the tangent vector at the last node of a link
virtual Standard_Boolean GetLastTangent(const Link& theLink,
gp_Dir& theDir) const = 0;
//! returns the normal to the surface at a given node
virtual Standard_Boolean GetNormal(Standard_Integer theNode,
gp_Dir& theDir) const = 0;
};
//! Constructor. If helper is NULL then the algorithm will
//! probably return a wrong result
Standard_EXPORT Poly_MakeLoops3D(const Helper* theHelper,
const Handle_NCollection_BaseAllocator& theAlloc);
protected:
Standard_EXPORT virtual Standard_Integer chooseLeftWay
(const Standard_Integer theNode,
const Standard_Integer theSegIndex,
const NCollection_List<Standard_Integer>& theLstIndS) const;
const Helper* getHelper () const
{
return static_cast<const Poly_MakeLoops3D::Helper*>
(Poly_MakeLoops::getHelper());
}
};
/**
* Implementation for 2D space
*/
class gp_Dir2d;
class Poly_MakeLoops2D: public Poly_MakeLoops
{
public:
//! The abstract helper class
class Helper: public Poly_MakeLoops::Helper
{
public:
// all the following methods should return False if
// it is impossible to return a valid direction
//! returns the tangent vector at the first node of a link
virtual Standard_Boolean GetFirstTangent(const Link& theLink,
gp_Dir2d& theDir) const = 0;
//! returns the tangent vector at the last node of a link
virtual Standard_Boolean GetLastTangent(const Link& theLink,
gp_Dir2d& theDir) const = 0;
};
//! Constructor. If helper is NULL then the algorithm will
//! probably return a wrong result
Standard_EXPORT Poly_MakeLoops2D(const Standard_Boolean theLeftWay,
const Helper* theHelper,
const Handle_NCollection_BaseAllocator& theAlloc);
protected:
Standard_EXPORT virtual Standard_Integer chooseLeftWay
(const Standard_Integer theNode,
const Standard_Integer theSegIndex,
const NCollection_List<Standard_Integer>& theLstIndS) const;
const Helper* getHelper () const
{
return static_cast<const Poly_MakeLoops2D::Helper*>
(Poly_MakeLoops::getHelper());
}
private:
//! this flag says that chooseLeftWay must choose the right way instead
Standard_Boolean myRightWay;
};
#endif

72
src/Poly/Poly_Polygon2D.cdl Executable file
View File

@@ -0,0 +1,72 @@
-- File: Poly_Polygon2D.cdl
-- Created: Thu Mar 9 16:29:00 1995
-- Author: Laurent PAINNOT
-- <lpa@metrox>
---Copyright: Matra Datavision 1995
class Polygon2D from Poly inherits TShared from MMgt
---Purpose: Provides a polygon in 2D space (for example, in the
-- parametric space of a surface). It is generally an
-- approximate representation of a curve.
-- A Polygon2D is defined by a table of nodes. Each node is
-- a 2D point. If the polygon is closed, the point of closure is
-- repeated at the end of the table of nodes.
uses Array1OfPnt2d from TColgp
raises NullObject from Standard
is
Create(Nodes: Array1OfPnt2d from TColgp)
returns mutable Polygon2D from Poly;
---Purpose: Constructs a 2D polygon defined by the table of points, <Nodes>.
Deflection(me) returns Real;
---Purpose: Returns the deflection of this polygon.
-- Deflection is used in cases where the polygon is an
-- approximate representation of a curve. Deflection
-- represents the maximum distance permitted between any
-- point on the curve and the corresponding point on the polygon.
-- By default the deflection value is equal to 0. An algorithm
-- using this 2D polygon with a deflection value equal to 0
-- considers that it is working with a true polygon and not with
-- an approximate representation of a curve. The Deflection
-- function is used to modify the deflection value of this polygon.
-- The deflection value can be used by any algorithm working with 2D polygons.
-- For example:
-- - An algorithm may use a unique deflection value for all
-- its polygons. In this case it is not necessary to use the
-- Deflection function.
-- - Or an algorithm may want to attach a different
-- deflection to each polygon. In this case, the Deflection
-- function is used to set a value on each polygon, and
-- later to fetch the value.
Deflection(me : mutable; D : Real);
---Purpose: Sets the deflection of this polygon to D
NbNodes(me) returns Integer;
---Purpose: Returns the number of nodes in this polygon.
-- Note: If the polygon is closed, the point of closure is
-- repeated at the end of its table of nodes. Thus, on a closed
-- triangle, the function NbNodes returns 4.
---C++: inline
Nodes(me) returns Array1OfPnt2d from TColgp
---Purpose: Returns the table of nodes for this polygon.
---C++: return const &
raises NullObject from Standard;
fields
myDeflection: Real;
myNbNodes: Integer;
myNodes: Array1OfPnt2d from TColgp;
end Polygon2D;

54
src/Poly/Poly_Polygon2D.cxx Executable file
View File

@@ -0,0 +1,54 @@
// File: Poly_Polygon2D.cxx
// Created: Thu Mar 9 16:36:49 1995
// Author: Laurent PAINNOT
// <lpa@metrox>
#include <Poly_Polygon2D.ixx>
#include <gp_Pnt2d.hxx>
//=======================================================================
//function : Poly_Polygon2D
//purpose :
//=======================================================================
Poly_Polygon2D::Poly_Polygon2D(const TColgp_Array1OfPnt2d& Nodes):
myDeflection(0.),
myNodes(1, Nodes.Length())
{
Standard_Integer i, j= 1;
for (i = Nodes.Lower(); i <= Nodes.Upper(); i++)
myNodes(j++) = Nodes(i);
}
//=======================================================================
//function : Deflection
//purpose :
//=======================================================================
Standard_Real Poly_Polygon2D::Deflection() const
{
return myDeflection;
}
//=======================================================================
//function : Deflection
//purpose :
//=======================================================================
void Poly_Polygon2D::Deflection(const Standard_Real D)
{
myDeflection = D;
}
//=======================================================================
//function : Nodes
//purpose :
//=======================================================================
const TColgp_Array1OfPnt2d& Poly_Polygon2D::Nodes() const
{
return myNodes;
}

16
src/Poly/Poly_Polygon2D.lxx Executable file
View File

@@ -0,0 +1,16 @@
// File: Poly_Polygon2D.lxx
// Created: Thu Mar 9 16:38:18 1995
// Author: Laurent PAINNOT
// <lpa@metrox>
//=======================================================================
//function : NbNodes
//purpose :
//=======================================================================
inline Standard_Integer Poly_Polygon2D::NbNodes() const
{
return myNodes.Length();
}

86
src/Poly/Poly_Polygon3D.cdl Executable file
View File

@@ -0,0 +1,86 @@
-- File: Poly_Polygon3D.cdl
-- Created: Tue Mar 7 11:19:36 1995
-- Author: Laurent PAINNOT
-- <lpa@metrox>
---Copyright: Matra Datavision 1995
class Polygon3D from Poly inherits TShared from MMgt
---Purpose: This class Provides a polygon in 3D space. It is generally an approximate representation of a curve.
-- A Polygon3D is defined by a table of nodes. Each node is
-- a 3D point. If the polygon is closed, the point of closure is
-- repeated at the end of the table of nodes.
-- If the polygon is an approximate representation of a curve,
-- you can associate with each of its nodes the value of the
-- parameter of the corresponding point on the curve.
uses Array1OfPnt from TColgp,
Array1OfReal from TColStd,
HArray1OfReal from TColStd
raises NullObject from Standard
is
Create(Nodes: Array1OfPnt from TColgp)
returns mutable Polygon3D from Poly;
---Purpose: onstructs a 3D polygon defined by the table of points, Nodes.
Create(Nodes: Array1OfPnt from TColgp;
Parameters: Array1OfReal from TColStd)
returns mutable Polygon3D from Poly;
---Purpose: Constructs a 3D polygon defined by
-- the table of points, Nodes, and the parallel table of
-- parameters, Parameters, where each value of the table
-- Parameters is the parameter of the corresponding point
-- on the curve approximated by the constructed polygon.
-- Warning
-- Both the Nodes and Parameters tables must have the
-- same bounds. This property is not checked at construction time.
Deflection(me) returns Real;
---Purpose: Returns the deflection of this polygon
Deflection(me : mutable; D : Real);
---Purpose: Sets the deflection of this polygon to D. See more on deflection in Poly_Polygon2D
NbNodes(me) returns Integer;
---Purpose: Returns the number of nodes in this polygon.
-- Note: If the polygon is closed, the point of closure is
-- repeated at the end of its table of nodes. Thus, on a closed
-- triangle the function NbNodes returns 4.
---C++: inline
Nodes(me) returns Array1OfPnt from TColgp
---Purpose: Returns the table of nodes for this polygon.
---C++: return const &
raises NullObject from Standard;
HasParameters(me) returns Boolean from Standard;
---Purpose: Returns the table of the parameters associated with each node in this polygon.
-- HasParameters function checks if parameters are associated with the nodes of this polygon.
Parameters(me) returns Array1OfReal from TColStd
---Purpose: Returns true if parameters are associated with the nodes
-- in this polygon.
---C++: return const &
raises NullObject from Standard;
ChangeParameters(me) returns Array1OfReal from TColStd
---Purpose: Returns the table of the parameters associated with each node in this polygon.
-- ChangeParameters function returnes the array as shared. Therefore if the table is selected by
-- reference you can, by simply modifying it, directly modify
-- the data structure of this polygon.
---C++: return &
raises NullObject from Standard;
fields
myDeflection: Real from Standard;
myNodes: Array1OfPnt from TColgp;
myParameters: HArray1OfReal from TColStd;
end Polygon3D;

106
src/Poly/Poly_Polygon3D.cxx Executable file
View File

@@ -0,0 +1,106 @@
// File: Poly_Polygon3D.cxx
// Created: Tue Mar 7 14:43:28 1995
// Author: Laurent PAINNOT
// <lpa@metrox>
#include <Poly_Polygon3D.ixx>
#include <gp_Pnt.hxx>
//=======================================================================
//function : Poly_Polygon3D
//purpose :
//=======================================================================
Poly_Polygon3D::Poly_Polygon3D(const TColgp_Array1OfPnt& Nodes):
myDeflection(0.),
myNodes(1, Nodes.Length())
{
Standard_Integer i, j= 1;
for (i = Nodes.Lower(); i <= Nodes.Upper(); i++)
myNodes(j++) = Nodes(i);
}
//=======================================================================
//function : Poly_Polygon3D
//purpose :
//=======================================================================
Poly_Polygon3D::Poly_Polygon3D(const TColgp_Array1OfPnt& Nodes,
const TColStd_Array1OfReal& P):
myDeflection(0.),
myNodes(1, Nodes.Length())
{
myParameters = new TColStd_HArray1OfReal(1, P.Length());
Standard_Integer i, j= 1;
for (i = Nodes.Lower(); i <= Nodes.Upper(); i++) {
myNodes(j) = Nodes(i);
myParameters->SetValue(j, P(i));
j++;
}
}
//=======================================================================
//function : Deflection
//purpose :
//=======================================================================
Standard_Real Poly_Polygon3D::Deflection() const
{
return myDeflection;
}
//=======================================================================
//function : Deflection
//purpose :
//=======================================================================
void Poly_Polygon3D::Deflection(const Standard_Real D)
{
myDeflection = D;
}
//=======================================================================
//function : Nodes
//purpose :
//=======================================================================
const TColgp_Array1OfPnt& Poly_Polygon3D::Nodes() const
{
return myNodes;
}
//=======================================================================
//function : HasParameters
//purpose :
//=======================================================================
Standard_Boolean Poly_Polygon3D::HasParameters() const
{
return !myParameters.IsNull();
}
//=======================================================================
//function : Parameters
//purpose :
//=======================================================================
const TColStd_Array1OfReal& Poly_Polygon3D::Parameters() const
{
return myParameters->Array1();
}
//=======================================================================
//function : ChangeParameters
//purpose :
//=======================================================================
TColStd_Array1OfReal& Poly_Polygon3D::ChangeParameters() const
{
return myParameters->ChangeArray1();
}

15
src/Poly/Poly_Polygon3D.lxx Executable file
View File

@@ -0,0 +1,15 @@
// File: Poly_Polygon3D.lxx
// Created: Thu Mar 9 16:50:45 1995
// Author: Laurent PAINNOT
// <lpa@metrox>
//=======================================================================
//function : NbNodes
//purpose :
//=======================================================================
inline Standard_Integer Poly_Polygon3D::NbNodes() const
{
return myNodes.Length();
}

View File

@@ -0,0 +1,94 @@
-- File: Poly_PolygonOnTriangulation.cdl
-- Created: Wed Feb 21 10:09:23 1996
-- Author: Laurent PAINNOT
-- <lpa@nonox>
---Copyright: Matra Datavision 1996
class PolygonOnTriangulation from Poly inherits TShared from MMgt
---Purpose: This class provides a polygon in 3D space, based on the triangulation
-- of a surface. It may be the approximate representation of a
-- curve on the surface, or more generally the shape.
-- A PolygonOnTriangulation is defined by a table of
-- nodes. Each node is an index in the table of nodes specific
-- to a triangulation, and represents a point on the surface. If
-- the polygon is closed, the index of the point of closure is
-- repeated at the end of the table of nodes.
-- If the polygon is an approximate representation of a curve
-- on a surface, you can associate with each of its nodes the
-- value of the parameter of the corresponding point on the
-- curve.represents a 3d Polygon
uses Array1OfInteger from TColStd,
Array1OfReal from TColStd,
HArray1OfReal from TColStd,
Triangulation from Poly
raises NullObject from Standard
is
Create(Nodes: Array1OfInteger from TColStd)
returns mutable PolygonOnTriangulation from Poly;
---Purpose: Constructs a 3D polygon on the triangulation of a shape,
-- defined by the table of nodes, <Nodes>.
Create(Nodes : Array1OfInteger from TColStd;
Parameters: Array1OfReal from TColStd)
returns mutable PolygonOnTriangulation from Poly;
---Purpose:
-- Constructs a 3D polygon on the triangulation of a shape, defined by:
-- - the table of nodes, Nodes, and the table of parameters, <Parameters>.
-- where:
-- - a node value is an index in the table of nodes specific
-- to an existing triangulation of a shape
-- - and a parameter value is the value of the parameter of
-- the corresponding point on the curve approximated by
-- the constructed polygon.
-- Warning
-- The tables Nodes and Parameters must be the same size.
-- This property is not checked at construction time.
Deflection(me) returns Real;
---Purpose: Returns the deflection of this polygon
Deflection(me : mutable; D : Real);
---Purpose: Sets the deflection of this polygon to D.
-- See more on deflection in Poly_Polygones2D.
NbNodes(me) returns Integer;
---Purpose:
-- Returns the number of nodes for this polygon.
-- Note: If the polygon is closed, the point of closure is
-- repeated at the end of its table of nodes. Thus, on a closed
-- triangle, the function NbNodes returns 4.
---C++: inline
Nodes(me) returns Array1OfInteger from TColStd
---Purpose: Returns the table of nodes for this polygon. A node value
-- is an index in the table of nodes specific to an existing
-- triangulation of a shape.
---C++: return const &
raises NullObject from Standard;
HasParameters(me) returns Boolean from Standard;
---Purpose:
-- Returns true if parameters are associated with the nodes in this polygon.
Parameters(me) returns HArray1OfReal from TColStd
--- Purpose: Returns the table of the parameters associated with each node in this polygon.
-- Warning
-- Use the function HasParameters to check if parameters
-- are associated with the nodes in this polygon.
--
raises NullObject from Standard;
fields
myDeflection : Real from Standard;
myNodes : Array1OfInteger from TColStd;
myParameters : HArray1OfReal from TColStd;
end PolygonOnTriangulation;

View File

@@ -0,0 +1,87 @@
// File: Poly_PolygonOnTriangulation.cxx
// Created: Tue Feb 20 14:43:28 1996
// Author: Laurent PAINNOT
// <lpa@nonox>
#include <Poly_PolygonOnTriangulation.ixx>
//=======================================================================
//function : Poly_PolygonOnTriangulation
//purpose :
//=======================================================================
Poly_PolygonOnTriangulation::Poly_PolygonOnTriangulation
(const TColStd_Array1OfInteger& Nodes) :
myDeflection(0.0),
myNodes(1, Nodes.Length())
{
myNodes = Nodes;
}
//=======================================================================
//function : Poly_PolygonOnTriangulation
//purpose :
//=======================================================================
Poly_PolygonOnTriangulation::Poly_PolygonOnTriangulation
(const TColStd_Array1OfInteger& Nodes,
const TColStd_Array1OfReal& Parameters):
myDeflection(0.0),
myNodes(1, Nodes.Length())
{
myNodes = Nodes;
myParameters = new TColStd_HArray1OfReal(1, Parameters.Length());
myParameters->ChangeArray1() = Parameters;
}
//=======================================================================
//function : Deflection
//purpose :
//=======================================================================
Standard_Real Poly_PolygonOnTriangulation::Deflection() const
{
return myDeflection;
}
//=======================================================================
//function : Deflection
//purpose :
//=======================================================================
void Poly_PolygonOnTriangulation::Deflection(const Standard_Real D)
{
myDeflection = D;
}
//=======================================================================
//function : Nodes
//purpose :
//=======================================================================
const TColStd_Array1OfInteger& Poly_PolygonOnTriangulation::Nodes() const
{
return myNodes;
}
//=======================================================================
//function : HasParameters
//purpose :
//=======================================================================
Standard_Boolean Poly_PolygonOnTriangulation::HasParameters() const
{
return (!myParameters.IsNull());
}
//=======================================================================
//function : Parameters
//purpose :
//=======================================================================
Handle(TColStd_HArray1OfReal) Poly_PolygonOnTriangulation::Parameters() const
{
return myParameters;
}

View File

@@ -0,0 +1,10 @@
//=======================================================================
//function : NbNodes
//purpose :
//=======================================================================
inline Standard_Integer Poly_PolygonOnTriangulation::NbNodes() const
{
return myNodes.Length();
}

64
src/Poly/Poly_Triangle.cdl Executable file
View File

@@ -0,0 +1,64 @@
-- File: Poly_Triangle.cdl
-- Created: Mon Mar 6 09:50:53 1995
-- Author: Laurent PAINNOT
-- <lpa@metrox>
---Copyright: Matra Datavision 1995
class Triangle from Poly
---Purpose: Describes a component triangle of a triangulation
-- (Poly_Triangulation object).
-- A Triangle is defined by a triplet of nodes. Each node is an
-- index in the table of nodes specific to an existing
-- triangulation of a shape, and represents a point on the surface.
raises
OutOfRange from Standard
is
Create returns Triangle from Poly;
---Purpose: Constructs a triangle and sets all indices to zero.
Create(N1,N2,N3 : Integer)
returns Triangle from Poly;
---Purpose: Constructs a triangle and sets its three indices
-- to N1, N2 and N3 respectively, where these node values
-- are indices in the table of nodes specific to an existing
-- triangulation of a shape.
Set(me : in out; N1,N2,N3 : Integer);
---Purpose: Sets the value of the three nodes of this triangle to N1, N2 and N3 respectively.
Set(me : in out; Index, Node : Integer)
---Purpose: Sets the value of the Indexth node of this triangle to Node.
-- Raises OutOfRange if Index is not in 1,2,3
raises
OutOfRange from Standard;
---C++: inline
Get(me; N1,N2,N3 : in out Integer);
--- Purpose: Returns the node indices of this triangle in N1, N2 and N3.
Value(me; Index : Integer) returns Integer
---Purpose: Get the node of given Index.
-- Raises OutOfRange from Standard if Index is not in 1,2,3
raises
OutOfRange from Standard;
---C++: inline
---C++: alias operator()
ChangeValue(me : in out; Index : Integer) returns Integer
---Purpose: Get the node of given Index.
-- Raises OutOfRange if Index is not in 1,2,3
raises
OutOfRange from Standard;
---C++: inline
---C++: return &
---C++: alias operator()
fields
myNodes : Integer [3];
end Triangle;

60
src/Poly/Poly_Triangle.cxx Executable file
View File

@@ -0,0 +1,60 @@
// File: Poly_Triangle.cxx
// Created: Mon Mar 6 10:47:39 1995
// Author: Laurent PAINNOT
// <lpa@metrox>
#include <Poly_Triangle.ixx>
//=======================================================================
//function : Poly_Triangle
//purpose :
//=======================================================================
Poly_Triangle::Poly_Triangle()
{
myNodes[0] = myNodes[1] = myNodes[2] = 0;
}
//=======================================================================
//function : Poly_Triangle
//purpose :
//=======================================================================
Poly_Triangle::Poly_Triangle(const Standard_Integer N1,
const Standard_Integer N2,
const Standard_Integer N3)
{
myNodes[0] = N1;
myNodes[1] = N2;
myNodes[2] = N3;
}
//=======================================================================
//function : Set
//purpose :
//=======================================================================
void Poly_Triangle::Set(const Standard_Integer N1,
const Standard_Integer N2,
const Standard_Integer N3)
{
myNodes[0] = N1;
myNodes[1] = N2;
myNodes[2] = N3;
}
//=======================================================================
//function : Get
//purpose :
//=======================================================================
void Poly_Triangle::Get(Standard_Integer& N1,
Standard_Integer& N2,
Standard_Integer& N3) const
{
N1 = myNodes[0];
N2 = myNodes[1];
N3 = myNodes[2];
}

41
src/Poly/Poly_Triangle.lxx Executable file
View File

@@ -0,0 +1,41 @@
// File: Poly_Triangle.lxx
// Created: Mon Mar 6 10:47:04 1995
// Author: Laurent PAINNOT
// <lpa@metrox>
#include <Standard_OutOfRange.hxx>
//=======================================================================
//function : Set
//purpose :
//=======================================================================
inline void Poly_Triangle::Set(const Standard_Integer Index, const Standard_Integer Node)
{
Standard_OutOfRange_Raise_if(Index < 1 || Index > 3,NULL);
myNodes[Index-1] = Node;
}
//=======================================================================
//function : Value
//purpose :
//=======================================================================
inline Standard_Integer Poly_Triangle::Value(const Standard_Integer Index) const
{
Standard_OutOfRange_Raise_if(Index < 1 || Index > 3,NULL);
return myNodes[Index-1];
}
//=======================================================================
//function : ChangeValue
//purpose :
//=======================================================================
inline Standard_Integer& Poly_Triangle::ChangeValue
(const Standard_Integer Index)
{
Standard_OutOfRange_Raise_if(Index < 1 || Index > 3,NULL);
return myNodes[Index-1];
}

180
src/Poly/Poly_Triangulation.cdl Executable file
View File

@@ -0,0 +1,180 @@
-- File: Poly_Triangulation.cdl
-- Created: Mon Mar 6 09:57:02 1995
-- Author: Laurent PAINNOT
-- <lpa@metrox>
---Copyright: Matra Datavision 1995
class Triangulation from Poly inherits TShared from MMgt
---Purpose: Provides a triangulation for a surface, a set of surfaces, or
-- more generally a shape.
-- A triangulation consists of an approximate representation
-- of the actual shape, using a collection of points and
-- triangles. The points are located on the surface. The
-- edges of the triangles connect adjacent points with a
-- straight line that approximates the true curve on the surface.
-- A triangulation comprises:
-- - A table of 3D nodes (3D points on the surface).
-- - A table of triangles. Each triangle (Poly_Triangle
-- object) comprises a triplet of indices in the table of 3D
-- nodes specific to the triangulation.
-- - A table of 2D nodes (2D points), parallel to the table of
-- 3D nodes. This table is optional. If it exists, the
-- coordinates of a 2D point are the (u, v) parameters
-- of the corresponding 3D point on the surface
-- approximated by the triangulation.
-- - A deflection (optional), which maximizes the distance
-- from a point on the surface to the corresponding point
-- on its approximate triangulation.
-- In many cases, algorithms do not need to work with the
-- exact representation of a surface. A triangular
-- representation induces simpler and more robust adjusting,
-- faster performances, and the results are as good.
uses
HArray1OfPnt2d from TColgp,
Array1OfPnt from TColgp,
Array1OfPnt2d from TColgp,
Array1OfTriangle from Poly,
HArray1OfShortReal from TShort,
Array1OfShortReal from TShort
raises
DomainError from Standard,
NullObject from Standard
is
Create(nbNodes, nbTriangles: Integer; UVNodes: Boolean)
returns mutable Triangulation from Poly;
---Purpose: Constructs a triangulation from a set of triangles. The
-- triangulation is initialized without a triangle or a node, but capable of
-- containing nbNodes nodes, and nbTriangles
-- triangles. Here the UVNodes flag indicates whether
-- 2D nodes will be associated with 3D ones, (i.e. to
-- enable a 2D representation).
Create(Nodes: Array1OfPnt from TColgp;
Triangles: Array1OfTriangle from Poly)
returns mutable Triangulation from Poly;
---Purpose: Constructs a triangulation from a set of triangles. The
-- triangulation is initialized with 3D points from Nodes and triangles
-- from Triangles.
Create(Nodes: Array1OfPnt from TColgp;
UVNodes: Array1OfPnt2d from TColgp;
Triangles: Array1OfTriangle from Poly)
returns mutable Triangulation from Poly;
---Purpose: Constructs a triangulation from a set of triangles. The
-- triangulation is initialized with 3D points from Nodes, 2D points from
-- UVNodes and triangles from Triangles, where
-- coordinates of a 2D point from UVNodes are the
-- (u, v) parameters of the corresponding 3D point
-- from Nodes on the surface approximated by the
-- constructed triangulation.
Deflection(me) returns Real;
---Purpose: Returns the deflection of this triangulation.
Deflection(me : mutable; D : Real);
---Purpose: Sets the deflection of this triangulation to D.
-- See more on deflection in Polygon2D
RemoveUVNodes(me : mutable);
---Purpose: Deallocates the UV nodes.
NbNodes(me) returns Integer;
---Purpose: Returns the number of nodes for this triangulation.
-- Null if the nodes are not yet defined.
---C++: inline
NbTriangles(me) returns Integer;
---Purpose: Returns the number of triangles for this triangulation.
-- Null if the Triangles are not yet defined.
---C++: inline
HasUVNodes(me) returns Boolean;
---Purpose: Returns true if 2D nodes are associated with 3D nodes for
-- this triangulation.
---C++: inline
Nodes(me) returns Array1OfPnt from TColgp
---Purpose: Returns the table of 3D nodes (3D points) for this triangulation.
---C++: return const &
raises NullObject from Standard;
ChangeNodes(me : mutable) returns Array1OfPnt from TColgp
---Purpose: Returns the table of 3D nodes (3D points) for this triangulation.
-- The returned array is
-- shared. Therefore if the table is selected by reference, you
-- can, by simply modifying it, directly modify the data
-- structure of this triangulation.
---C++: return &
raises NullObject from Standard;
UVNodes(me) returns Array1OfPnt2d from TColgp
---Purpose: Returns the table of 2D nodes (2D points) associated with
-- each 3D node of this triangulation.
-- The function HasUVNodes checks if 2D nodes
-- are associated with the 3D nodes of this triangulation.
-- Const reference on the 2d nodes values.
---C++: return const &
raises NullObject from Standard;
ChangeUVNodes(me : mutable) returns Array1OfPnt2d from TColgp
---Purpose: Returns the table of 2D nodes (2D points) associated with
-- each 3D node of this triangulation.
-- Function ChangeUVNodes shares the returned array.
-- Therefore if the table is selected by reference,
-- you can, by simply modifying it, directly modify the data
-- structure of this triangulation.
---C++: return &
raises NullObject from Standard;
Triangles(me) returns Array1OfTriangle from Poly
---Purpose: Returns the table of triangles for this triangulation.
---C++: return const &
raises NullObject from Standard;
ChangeTriangles(me : mutable) returns Array1OfTriangle from Poly
---Purpose: Returns the table of triangles for this triangulation.
-- Function ChangeUVNodes shares the returned array.
-- Therefore if the table is selected by reference,
-- you can, by simply modifying it, directly modify the data
-- structure of this triangulation.
---C++: return &
raises NullObject from Standard;
SetNormals(me : mutable; theNormals : HArray1OfShortReal from TShort)
---Purpose: Sets the table of node normals.
-- raises exception if length of theNormals != 3*NbNodes
raises DomainError from Standard;
Normals(me) returns Array1OfShortReal from TShort
---C++: return const &
-- raises exception if array of normals is empty or
-- its length != 3*NbNodes
raises NullObject from Standard;
ChangeNormals(me : mutable) returns Array1OfShortReal from TShort
---C++: return &
-- raises exception if array of normals is empty or
-- its length != 3*NbNodes
raises NullObject from Standard;
HasNormals(me) returns Boolean from Standard;
fields
myDeflection : Real;
myNbNodes : Integer;
myNbTriangles : Integer;
myNodes : Array1OfPnt from TColgp;
myUVNodes : HArray1OfPnt2d from TColgp;
myTriangles : Array1OfTriangle from Poly;
---- Optional normals ---
myNormals : HArray1OfShortReal from TShort;
end Triangulation;

227
src/Poly/Poly_Triangulation.cxx Executable file
View File

@@ -0,0 +1,227 @@
// File: Poly_Triangulation.cxx
// Created: Mon Mar 6 10:54:09 1995
// Author: Laurent PAINNOT
// <lpa@metrox>
#include <Poly_Triangulation.ixx>
#include <gp_Pnt.hxx>
#include <Poly_Triangle.hxx>
//=======================================================================
//function : Poly_Triangulation
//purpose :
//=======================================================================
Poly_Triangulation::Poly_Triangulation(const Standard_Integer NbNodes,
const Standard_Integer NbTriangles,
const Standard_Boolean UVNodes) :
myDeflection(0),
myNbNodes(NbNodes),
myNbTriangles(NbTriangles),
myNodes(1, NbNodes),
myTriangles(1, NbTriangles)
{
if (UVNodes) myUVNodes = new TColgp_HArray1OfPnt2d(1, myNbNodes);
}
//=======================================================================
//function : Poly_Triangulation
//purpose :
//=======================================================================
Poly_Triangulation::Poly_Triangulation(const TColgp_Array1OfPnt& Nodes,
const Poly_Array1OfTriangle& Triangles) :
myDeflection(0),
myNbNodes(Nodes.Length()),
myNbTriangles(Triangles.Length()),
myNodes(1, Nodes.Length()),
myTriangles(1, Triangles.Length())
{
myNodes = Nodes;
myTriangles = Triangles;
}
//=======================================================================
//function : Poly_Triangulation
//purpose :
//=======================================================================
Poly_Triangulation::Poly_Triangulation(const TColgp_Array1OfPnt& Nodes,
const TColgp_Array1OfPnt2d& UVNodes,
const Poly_Array1OfTriangle& Triangles) :
myDeflection(0),
myNbNodes(Nodes.Length()),
myNbTriangles(Triangles.Length()),
myNodes(1, Nodes.Length()),
myTriangles(1, Triangles.Length())
{
myNodes = Nodes;
myTriangles = Triangles;
myUVNodes = new TColgp_HArray1OfPnt2d(1, myNbNodes);
myUVNodes->ChangeArray1() = UVNodes;
}
//=======================================================================
//function : Deflection
//purpose :
//=======================================================================
Standard_Real Poly_Triangulation::Deflection() const
{
return myDeflection;
}
//=======================================================================
//function : Deflection
//purpose :
//=======================================================================
void Poly_Triangulation::Deflection(const Standard_Real D)
{
myDeflection = D;
}
//=======================================================================
//function : RemoveUVNodes
//purpose :
//=======================================================================
void Poly_Triangulation::RemoveUVNodes()
{
myUVNodes.Nullify();
}
//=======================================================================
//function : Nodes
//purpose :
//=======================================================================
const TColgp_Array1OfPnt& Poly_Triangulation::Nodes() const
{
return myNodes;
}
//=======================================================================
//function : ChangeNodes
//purpose :
//=======================================================================
TColgp_Array1OfPnt& Poly_Triangulation::ChangeNodes()
{
return myNodes;
}
//=======================================================================
//function : UVNodes
//purpose :
//=======================================================================
const TColgp_Array1OfPnt2d& Poly_Triangulation::UVNodes() const
{
return myUVNodes->Array1();
}
//=======================================================================
//function : ChangeUVNodes
//purpose :
//=======================================================================
TColgp_Array1OfPnt2d& Poly_Triangulation::ChangeUVNodes()
{
return myUVNodes->ChangeArray1();
}
//=======================================================================
//function : Triangles
//purpose :
//=======================================================================
const Poly_Array1OfTriangle& Poly_Triangulation::Triangles() const
{
return myTriangles;
}
//=======================================================================
//function : ChangeTriangles
//purpose :
//=======================================================================
Poly_Array1OfTriangle& Poly_Triangulation::ChangeTriangles()
{
return myTriangles;
}
//=======================================================================
//function : SetNormals
//purpose :
//=======================================================================
void Poly_Triangulation::SetNormals
(const Handle(TShort_HArray1OfShortReal)& theNormals)
{
if(theNormals.IsNull() || theNormals->Length() != 3*myNbNodes) {
Standard_DomainError::Raise("Poly_Triangulation::SetNormals : wrong length");
}
myNormals = theNormals;
}
//=======================================================================
//function : Normals
//purpose :
//=======================================================================
const TShort_Array1OfShortReal& Poly_Triangulation::Normals() const
{
if(myNormals.IsNull() || myNormals->Length() != 3*myNbNodes) {
Standard_NullObject::Raise("Poly_Triangulation::Normals : "
"wrong length or null array");
}
return myNormals->Array1();
}
//=======================================================================
//function : ChangeNormals
//purpose :
//=======================================================================
TShort_Array1OfShortReal& Poly_Triangulation::ChangeNormals()
{
if(myNormals.IsNull() || myNormals->Length() != 3*myNbNodes) {
Standard_NullObject::Raise("Poly_Triangulation::ChangeNormals : "
"wrong length or null array");
}
return myNormals->ChangeArray1();
}
//=======================================================================
//function : HasNormals
//purpose :
//=======================================================================
Standard_Boolean Poly_Triangulation::HasNormals() const
{
if(myNormals.IsNull() || myNormals->Length() != 3*myNbNodes) {
return Standard_False;
}
return Standard_True;
}

35
src/Poly/Poly_Triangulation.lxx Executable file
View File

@@ -0,0 +1,35 @@
// File: Poly_Triangulation.lxx
// Created: Mon Mar 6 10:53:09 1995
// Author: Laurent PAINNOT
// <lpa@metrox>
//=======================================================================
//function : NbNodes
//purpose :
//=======================================================================
inline Standard_Integer Poly_Triangulation::NbNodes() const
{
return myNbNodes;
}
//=======================================================================
//function : NbTriangles
//purpose :
//=======================================================================
inline Standard_Integer Poly_Triangulation::NbTriangles() const
{
return myNbTriangles;
}
//=======================================================================
//function : HasUVNodes
//purpose :
//=======================================================================
inline Standard_Boolean Poly_Triangulation::HasUVNodes() const
{
return !myUVNodes.IsNull();
}