1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-04-16 10:08:36 +03:00
occt/src/BRepMesh/BRepMesh_DataStructureOfDelaun.cxx

565 lines
17 KiB
C++

// Created on: 1993-05-11
// Created by: Didier PIFFAULT
// Copyright (c) 1993-1999 Matra Datavision
// Copyright (c) 1999-2014 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#include <BRepMesh_DataStructureOfDelaun.hxx>
#include <BRepBuilderAPI_MakeEdge.hxx>
#include <BRepBuilderAPI_MakeVertex.hxx>
#include <BRepMesh_Edge.hxx>
#include <BRep_Builder.hxx>
#include <BRepTools.hxx>
#include <Standard_ErrorHandler.hxx>
IMPLEMENT_STANDARD_RTTIEXT(BRepMesh_DataStructureOfDelaun, Standard_Transient)
//=======================================================================
//function : BRepMesh_DataStructureOfDelaun
//purpose :
//=======================================================================
BRepMesh_DataStructureOfDelaun::BRepMesh_DataStructureOfDelaun(
const Handle(NCollection_IncAllocator)& theAllocator,
const Standard_Integer theReservedNodeSize)
: myAllocator (theAllocator),
myNodes (new BRepMesh_VertexTool(myAllocator)),
myNodeLinks (theReservedNodeSize * 3, myAllocator),
myLinks (theReservedNodeSize * 3, myAllocator),
myDelLinks (myAllocator),
myElements (theReservedNodeSize * 2, myAllocator)
{
}
//=======================================================================
//function : SubstituteNode
//purpose :
//=======================================================================
Standard_Integer BRepMesh_DataStructureOfDelaun::AddNode(
const BRepMesh_Vertex& theNode,
const Standard_Boolean isForceAdd)
{
const Standard_Integer aNodeId = myNodes->Add(theNode, isForceAdd);
if (!myNodeLinks.IsBound(aNodeId))
myNodeLinks.Bind(aNodeId, IMeshData::ListOfInteger(myAllocator));
return aNodeId;
}
//=======================================================================
//function : SubstituteNode
//purpose :
//=======================================================================
Standard_Boolean BRepMesh_DataStructureOfDelaun::SubstituteNode(
const Standard_Integer theIndex,
const BRepMesh_Vertex& theNewNode)
{
if (myNodes->FindIndex(theNewNode) != 0)
return Standard_False;
myNodes->Substitute(theIndex, theNewNode);
return Standard_True;
}
//=======================================================================
//function : AddLink
//purpose :
//=======================================================================
Standard_Integer BRepMesh_DataStructureOfDelaun::AddLink(
const BRepMesh_Edge& theLink)
{
Standard_Integer aLinkIndex = IndexOf(theLink);
if (aLinkIndex > 0)
{
return theLink.IsSameOrientation(GetLink(aLinkIndex)) ?
aLinkIndex : -aLinkIndex;
}
BRepMesh_PairOfIndex aPair;
if (!myDelLinks.IsEmpty())
{
aLinkIndex = myDelLinks.First();
myLinks.Substitute(aLinkIndex, theLink, aPair);
myDelLinks.RemoveFirst();
}
else
aLinkIndex = myLinks.Add(theLink, aPair);
const Standard_Integer aLinkId = Abs(aLinkIndex);
linksConnectedTo(theLink.FirstNode()).Append(aLinkId);
linksConnectedTo(theLink.LastNode() ).Append(aLinkId);
myLinksOfDomain.Add(aLinkIndex);
return aLinkIndex;
}
//=======================================================================
//function : SubstituteLink
//purpose :
//=======================================================================
Standard_Boolean BRepMesh_DataStructureOfDelaun::SubstituteLink(
const Standard_Integer theIndex,
const BRepMesh_Edge& theNewLink)
{
BRepMesh_PairOfIndex aPair;
BRepMesh_Edge aLink = GetLink(theIndex);
if (aLink.Movability() == BRepMesh_Deleted)
{
myLinks.Substitute(theIndex, theNewLink, aPair);
return Standard_True;
}
if (IndexOf(theNewLink) != 0)
return Standard_False;
aLink.SetMovability(BRepMesh_Deleted);
myLinks.Substitute(theIndex, aLink, aPair);
cleanLink(theIndex, aLink);
const Standard_Integer aLinkId = Abs(theIndex);
linksConnectedTo(theNewLink.FirstNode()).Append(aLinkId);
linksConnectedTo(theNewLink.LastNode() ).Append(aLinkId);
myLinks.Substitute(theIndex, theNewLink, aPair);
return Standard_True;
}
//=======================================================================
//function : ForceRemoveLink
//purpose :
//=======================================================================
void BRepMesh_DataStructureOfDelaun::RemoveLink(
const Standard_Integer theIndex,
const Standard_Boolean isForce)
{
BRepMesh_Edge& aLink = (BRepMesh_Edge&)GetLink(theIndex);
if (aLink.Movability() == BRepMesh_Deleted ||
(!isForce && aLink.Movability() != BRepMesh_Free) ||
ElementsConnectedTo(theIndex).Extent() != 0)
{
return;
}
cleanLink(theIndex, aLink);
aLink.SetMovability(BRepMesh_Deleted);
myLinksOfDomain.Remove(theIndex);
myDelLinks.Append (theIndex);
}
//=======================================================================
//function : cleanLink
//purpose :
//=======================================================================
void BRepMesh_DataStructureOfDelaun::cleanLink(
const Standard_Integer theIndex,
const BRepMesh_Edge& theLink)
{
for (Standard_Integer i = 0; i < 2; ++i)
{
const Standard_Integer aNodeId = (i == 0) ?
theLink.FirstNode() : theLink.LastNode();
IMeshData::ListOfInteger& aLinkList = linksConnectedTo(aNodeId);
IMeshData::ListOfInteger::Iterator aLinkIt(aLinkList);
for(; aLinkIt.More(); aLinkIt.Next())
{
if (aLinkIt.Value() == theIndex)
{
aLinkList.Remove(aLinkIt);
break;
}
}
}
}
//=======================================================================
//function : AddElement
//purpose :
//=======================================================================
Standard_Integer BRepMesh_DataStructureOfDelaun::AddElement(
const BRepMesh_Triangle& theElement)
{
myElements.Append(theElement);
Standard_Integer aElementIndex = myElements.Size();
myElementsOfDomain.Add(aElementIndex);
const Standard_Integer (&e)[3] = theElement.myEdges;
for (Standard_Integer i = 0; i < 3; ++i)
myLinks(e[i]).Append(aElementIndex);
return aElementIndex;
}
//=======================================================================
//function : RemoveElement
//purpose :
//=======================================================================
void BRepMesh_DataStructureOfDelaun::RemoveElement(
const Standard_Integer theIndex)
{
BRepMesh_Triangle& aElement = (BRepMesh_Triangle&)GetElement(theIndex);
if (aElement.Movability() == BRepMesh_Deleted)
return;
cleanElement(theIndex, aElement);
aElement.SetMovability(BRepMesh_Deleted);
myElementsOfDomain.Remove(theIndex);
}
//=======================================================================
//function : cleanElement
//purpose :
//=======================================================================
void BRepMesh_DataStructureOfDelaun::cleanElement(
const Standard_Integer theIndex,
const BRepMesh_Triangle& theElement)
{
if (theElement.Movability() != BRepMesh_Free)
return;
const Standard_Integer(&e)[3] = theElement.myEdges;
for (Standard_Integer i = 0; i < 3; ++i)
removeElementIndex(theIndex, myLinks(e[i]));
}
//=======================================================================
//function : removeElementIndex
//purpose :
//=======================================================================
void BRepMesh_DataStructureOfDelaun::removeElementIndex(
const Standard_Integer theIndex,
BRepMesh_PairOfIndex& thePair)
{
for (Standard_Integer i = 1, n = thePair.Extent(); i <= n; ++i)
{
if (thePair.Index(i) == theIndex)
{
thePair.RemoveIndex(i);
return;
}
}
}
//=======================================================================
//function : SubstituteElement
//purpose :
//=======================================================================
Standard_Boolean BRepMesh_DataStructureOfDelaun::SubstituteElement(
const Standard_Integer theIndex,
const BRepMesh_Triangle& theNewElement)
{
const BRepMesh_Triangle& aElement = GetElement(theIndex);
if (aElement.Movability() == BRepMesh_Deleted)
{
myElements(theIndex) = theNewElement;
return Standard_True;
}
cleanElement(theIndex, aElement);
// Warning: here new element and old element should have different Hash code
myElements(theIndex) = theNewElement;
const Standard_Integer(&e)[3] = theNewElement.myEdges;
for (Standard_Integer i = 0; i < 3; ++i)
myLinks(e[i]).Append(theIndex);
return Standard_True;
}
//=======================================================================
//function : ElementNodes
//purpose :
//=======================================================================
void BRepMesh_DataStructureOfDelaun::ElementNodes(
const BRepMesh_Triangle& theElement,
Standard_Integer (&theNodes)[3])
{
const Standard_Integer(&e)[3] = theElement.myEdges;
const Standard_Boolean(&o)[3] = theElement.myOrientations;
const BRepMesh_Edge& aLink1 = GetLink(e[0]);
if (o[0])
{
theNodes[0] = aLink1.FirstNode();
theNodes[1] = aLink1.LastNode();
}
else
{
theNodes[1] = aLink1.FirstNode();
theNodes[0] = aLink1.LastNode();
}
const BRepMesh_Edge& aLink2 = GetLink(e[2]);
if (o[2])
theNodes[2] = aLink2.FirstNode();
else
theNodes[2] = aLink2.LastNode();
}
//=======================================================================
//function : ClearDomain
//purpose :
//=======================================================================
void BRepMesh_DataStructureOfDelaun::ClearDomain()
{
IMeshData::MapOfInteger aFreeEdges;
IMeshData::IteratorOfMapOfInteger aElementIt(myElementsOfDomain);
for (; aElementIt.More(); aElementIt.Next())
{
const Standard_Integer aElementId = aElementIt.Key();
BRepMesh_Triangle& aElement = (BRepMesh_Triangle&)GetElement(aElementId);
const Standard_Integer(&e)[3] = aElement.myEdges;
for (Standard_Integer i = 0; i < 3; ++i)
aFreeEdges.Add(e[i]);
cleanElement(aElementId, aElement);
aElement.SetMovability(BRepMesh_Deleted);
}
myElementsOfDomain.Clear();
IMeshData::IteratorOfMapOfInteger aEdgeIt(aFreeEdges);
for (; aEdgeIt.More(); aEdgeIt.Next())
RemoveLink(aEdgeIt.Key());
}
//=======================================================================
//function : clearDeletedLinks
//purpose :
//=======================================================================
void BRepMesh_DataStructureOfDelaun::clearDeletedLinks()
{
Standard_Integer aLastLiveItem = NbLinks();
while (!myDelLinks.IsEmpty())
{
while (aLastLiveItem > 0)
{
if (GetLink(aLastLiveItem).Movability() != BRepMesh_Deleted)
break;
myLinks.RemoveLast();
--aLastLiveItem;
}
Standard_Integer aDelItem = myDelLinks.First();
myDelLinks.RemoveFirst();
if (aDelItem > aLastLiveItem)
continue;
BRepMesh_Edge aLink = GetLink(aLastLiveItem);
BRepMesh_PairOfIndex& aPair = myLinks(aLastLiveItem);
myLinks.RemoveLast();
myLinks.Substitute(aDelItem, aLink, aPair);
myLinksOfDomain.Remove(aLastLiveItem);
myLinksOfDomain.Add(aDelItem);
--aLastLiveItem;
const Standard_Integer aLastLiveItemId = aLastLiveItem + 1;
IMeshData::ListOfInteger::Iterator aLinkIt;
// update link references
for (Standard_Integer i = 0; i < 2; ++i)
{
const Standard_Integer aCurNodeId = (i == 0) ?
aLink.FirstNode() : aLink.LastNode();
for (aLinkIt.Init(linksConnectedTo(aCurNodeId)); aLinkIt.More(); aLinkIt.Next())
{
Standard_Integer& aLinkId = aLinkIt.ChangeValue();
if (aLinkId == aLastLiveItemId)
{
aLinkId = aDelItem;
break;
}
}
}
// update elements references
for(Standard_Integer j = 1, jn = aPair.Extent(); j <= jn; ++j)
{
Standard_Integer e[3];
Standard_Boolean o[3];
const BRepMesh_Triangle& aElement = GetElement(aPair.Index(j));
aElement.Edges(e, o);
for (Standard_Integer i = 0; i < 3; ++i)
{
if (e[i] == aLastLiveItemId)
{
e[i] = aDelItem;
break;
}
}
myElements(aLinkIt.Value()) = BRepMesh_Triangle(e, o, aElement.Movability());
}
}
}
//=======================================================================
//function : clearDeletedNodes
//purpose :
//=======================================================================
void BRepMesh_DataStructureOfDelaun::clearDeletedNodes()
{
IMeshData::ListOfInteger& aDelNodes =
(IMeshData::ListOfInteger&)myNodes->GetListOfDelNodes();
Standard_Integer aLastLiveItem = NbNodes();
while (!aDelNodes.IsEmpty())
{
while (aLastLiveItem > 0)
{
if (GetNode(aLastLiveItem).Movability() != BRepMesh_Deleted)
break;
myNodes->RemoveLast();
--aLastLiveItem;
}
Standard_Integer aDelItem = aDelNodes.First();
aDelNodes.RemoveFirst();
if (aDelItem > aLastLiveItem)
continue;
BRepMesh_Vertex aNode = GetNode(aLastLiveItem);
IMeshData::ListOfInteger& aLinkList = linksConnectedTo(aLastLiveItem);
myNodes->RemoveLast();
--aLastLiveItem;
myNodes->Substitute(aDelItem, aNode);
myNodeLinks.ChangeFind(aDelItem) = aLinkList;
const Standard_Integer aLastLiveItemId = aLastLiveItem + 1;
IMeshData::ListOfInteger::Iterator aLinkIt(aLinkList);
for (; aLinkIt.More(); aLinkIt.Next())
{
const Standard_Integer aLinkId = aLinkIt.Value();
const BRepMesh_Edge& aLink = GetLink(aLinkId);
BRepMesh_PairOfIndex& aPair = myLinks(aLinkId);
Standard_Integer v[2] = { aLink.FirstNode(), aLink.LastNode() };
if (v[0] == aLastLiveItemId)
v[0] = aDelItem;
else if (v[1] == aLastLiveItemId)
v[1] = aDelItem;
myLinks.Substitute(aLinkId,
BRepMesh_Edge(v[0], v[1], aLink.Movability()), aPair);
}
}
}
//=======================================================================
//function : Statistics
//purpose :
//=======================================================================
void BRepMesh_DataStructureOfDelaun::Statistics(Standard_OStream& theStream) const
{
theStream << " Map of nodes : \n";
myNodes->Statistics(theStream);
theStream << "\n Deleted nodes : " << myNodes->GetListOfDelNodes().Extent() << std::endl;
theStream << "\n\n Map of Links : \n";
myLinks.Statistics(theStream);
theStream << "\n Deleted links : " << myDelLinks.Extent() << std::endl;
theStream << "\n\n Map of elements : \n";
theStream << "\n Elements : " << myElements.Size() << std::endl;
}
//=======================================================================
//function : BRepMesh_Write
//purpose :
// Global function not declared in any public header, intended for use
// from debugger prompt (Command Window in Visual Studio).
//
// Stores the mesh data structure to BRep file with the given name.
//=======================================================================
Standard_CString BRepMesh_Dump(void* theMeshHandlePtr,
Standard_CString theFileNameStr)
{
if (theMeshHandlePtr == 0 || theFileNameStr == 0)
{
return "Error: file name or mesh data is null";
}
Handle(BRepMesh_DataStructureOfDelaun) aMeshData =
*(Handle(BRepMesh_DataStructureOfDelaun)*)theMeshHandlePtr;
if (aMeshData.IsNull())
return "Error: mesh data is empty";
TopoDS_Compound aMesh;
BRep_Builder aBuilder;
aBuilder.MakeCompound(aMesh);
try
{
OCC_CATCH_SIGNALS
if (aMeshData->LinksOfDomain().IsEmpty())
{
const Standard_Integer aNodesNb = aMeshData->NbNodes();
for (Standard_Integer i = 1; i <= aNodesNb; ++i)
{
const gp_XY& aNode = aMeshData->GetNode(i).Coord();
gp_Pnt aPnt(aNode.X(), aNode.Y(), 0.);
aBuilder.Add(aMesh, BRepBuilderAPI_MakeVertex(aPnt));
}
}
else
{
IMeshData::IteratorOfMapOfInteger aLinksIt(aMeshData->LinksOfDomain());
for (; aLinksIt.More(); aLinksIt.Next())
{
const BRepMesh_Edge& aLink = aMeshData->GetLink(aLinksIt.Key());
gp_Pnt aPnt[2];
for (Standard_Integer i = 0; i < 2; ++i)
{
const Standard_Integer aNodeId =
(i == 0) ? aLink.FirstNode() : aLink.LastNode();
const gp_XY& aNode = aMeshData->GetNode(aNodeId).Coord();
aPnt[i] = gp_Pnt(aNode.X(), aNode.Y(), 0.);
}
if (aPnt[0].SquareDistance(aPnt[1]) < Precision::SquareConfusion())
continue;
aBuilder.Add(aMesh, BRepBuilderAPI_MakeEdge(aPnt[0], aPnt[1]));
}
}
if (!BRepTools::Write(aMesh, theFileNameStr))
return "Error: write failed";
}
catch (Standard_Failure const& anException)
{
return anException.GetMessageString();
}
return theFileNameStr;
}
void BRepMesh_DataStructureOfDelaun::Dump(Standard_CString theFileNameStr)
{
Handle(BRepMesh_DataStructureOfDelaun) aMeshData (this);
BRepMesh_Dump((void*)&aMeshData, theFileNameStr);
}