geom/src/GEOMUtils/GEOMUtils_Hatcher.cxx
2016-03-15 15:27:04 +03:00

399 lines
12 KiB
C++
Executable File

// Copyright (C) 2007-2016 CEA/DEN, EDF R&D, OPEN CASCADE
//
// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
//
#include <GEOMUtils_Hatcher.hxx>
#include <BRep_Tool.hxx>
#include <BRepTools.hxx>
#include <Geom2d_Line.hxx>
#include <Geom2d_TrimmedCurve.hxx>
#include <Geom2dAdaptor_Curve.hxx>
#include <TopExp_Explorer.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Edge.hxx>
#include <HatchGen_Domain.hxx>
static Standard_Real IntersectorConfusion = 1.e-10; // -8;
static Standard_Real IntersectorTangency = 1.e-10; // -8;
static Standard_Real HatcherConfusion2d = 1.e-8;
static Standard_Real HatcherConfusion3d = 1.e-8;
// VTK uses float numbers - Precision::Infinite() is double and
// can not be accepted.
static float InfiniteValue = 1e38;
//=======================================================================
//function : GEOMUtils_Hatcher
//purpose :
//=======================================================================
GEOMUtils::Hatcher::Hatcher(const TopoDS_Face &theFace)
: myHatcher(Geom2dHatch_Intersector (IntersectorConfusion, IntersectorTangency),
HatcherConfusion2d, HatcherConfusion3d,
Standard_True, Standard_False),
myFace (theFace),
myIsDone (Standard_False),
myUMin (0.),
myUMax (0.),
myVMin (0.),
myVMax (0.)
{
// Get bounds.
BRepTools::UVBounds (theFace, myUMin, myUMax, myVMin, myVMax);
Standard_Boolean InfiniteUMin = Precision::IsNegativeInfinite (myUMin);
Standard_Boolean InfiniteUMax = Precision::IsPositiveInfinite (myUMax);
Standard_Boolean InfiniteVMin = Precision::IsNegativeInfinite (myVMin);
Standard_Boolean InfiniteVMax = Precision::IsPositiveInfinite (myVMax);
if (InfiniteUMin && InfiniteUMax) {
myUMin = - InfiniteValue;
myUMax = InfiniteValue;
} else if (InfiniteUMin) {
myUMin = myUMax - InfiniteValue;
} else if (InfiniteUMax) {
myUMax = myUMin + InfiniteValue;
}
if (InfiniteVMin && InfiniteVMax) {
myVMin = - InfiniteValue;
myVMax = InfiniteValue;
} else if (InfiniteVMin) {
myVMin = myVMax - InfiniteValue;
} else if (InfiniteVMax) {
myVMax = myVMin + InfiniteValue;
}
// Add edges
TopExp_Explorer anExpEdges(theFace, TopAbs_EDGE);
const Standard_Real aParamTol = Precision::PConfusion();
for (; anExpEdges.More(); anExpEdges.Next()) {
const TopoDS_Edge& anEdge = TopoDS::Edge (anExpEdges.Current());
Standard_Real U1, U2;
const Handle(Geom2d_Curve) PCurve =
BRep_Tool::CurveOnSurface (anEdge, theFace, U1, U2);
if (PCurve.IsNull()) {
continue;
}
if (U1 == U2) {
continue;
}
//-- Test if a TrimmedCurve is necessary
if(Abs(PCurve->FirstParameter() - U1) <= aParamTol &&
Abs(PCurve->LastParameter() - U2) <= aParamTol) {
myHatcher.AddElement(PCurve, anEdge.Orientation());
} else {
if (!PCurve->IsPeriodic()) {
Handle(Geom2d_TrimmedCurve) TrimPCurve =
Handle(Geom2d_TrimmedCurve)::DownCast(PCurve);
if (!TrimPCurve.IsNull()) {
Handle(Geom2d_Curve) aBasisCurve = TrimPCurve->BasisCurve();
if (aBasisCurve->FirstParameter() - U1 > aParamTol ||
U2 - aBasisCurve->LastParameter() > aParamTol) {
myHatcher.AddElement (PCurve, anEdge.Orientation());
return;
}
} else {
if (PCurve->FirstParameter() - U1 > aParamTol) {
U1 = PCurve->FirstParameter();
}
if (U2 - PCurve->LastParameter() > aParamTol) {
U2=PCurve->LastParameter();
}
}
}
Handle (Geom2d_TrimmedCurve) TrimPCurve =
new Geom2d_TrimmedCurve (PCurve, U1, U2);
myHatcher.AddElement (TrimPCurve, anEdge.Orientation());
}
}
}
//=======================================================================
//function : Init
//purpose :
//=======================================================================
void GEOMUtils::Hatcher::Init(const Standard_Integer theNbIsos)
{
Init(theNbIsos, theNbIsos);
}
//=======================================================================
//function : Init
//purpose :
//=======================================================================
void GEOMUtils::Hatcher::Init(const Standard_Integer theNbIsoU,
const Standard_Integer theNbIsoV)
{
// Initialize data.
Clear();
if (theNbIsoU > 0 || theNbIsoV > 0) {
Standard_Integer IIso;
Standard_Real DeltaU = Abs (myUMax - myUMin);
Standard_Real DeltaV = Abs (myVMax - myVMin);
Standard_Real confusion = Min (DeltaU, DeltaV) * myHatcher.Confusion3d();
myHatcher.Confusion3d (confusion);
if (theNbIsoU > 0) {
myUPrm = new TColStd_HArray1OfReal (1, theNbIsoU);
myUInd = new TColStd_HArray1OfInteger(1, theNbIsoU, 0);
Standard_Real StepU = DeltaU / (Standard_Real) theNbIsoU;
if (StepU > confusion) {
Standard_Real UPrm = myUMin + StepU / 2.;
gp_Dir2d Dir (0., 1.);
for (IIso = 1; IIso <= theNbIsoU; IIso++) {
myUPrm->SetValue(IIso, UPrm);
gp_Pnt2d Ori (UPrm, 0.);
Geom2dAdaptor_Curve HCur (new Geom2d_Line (Ori, Dir));
myUInd->SetValue(IIso, myHatcher.AddHatching(HCur));
UPrm += StepU;
}
}
}
if (theNbIsoV > 0) {
myVPrm = new TColStd_HArray1OfReal (1, theNbIsoV);
myVInd = new TColStd_HArray1OfInteger(1, theNbIsoV, 0);
Standard_Real StepV = DeltaV / (Standard_Real) theNbIsoV;
if (StepV > confusion) {
Standard_Real VPrm = myVMin + StepV / 2.;
gp_Dir2d Dir (1., 0.);
for (IIso = 1; IIso <= theNbIsoV; IIso++) {
myVPrm->SetValue(IIso, VPrm);
gp_Pnt2d Ori (0., VPrm);
Geom2dAdaptor_Curve HCur (new Geom2d_Line (Ori, Dir));
myVInd->SetValue(IIso, myHatcher.AddHatching(HCur));
VPrm += StepV;
}
}
}
}
}
//=======================================================================
//function : Init
//purpose :
//=======================================================================
void GEOMUtils::Hatcher::Init(const GeomAbs_IsoType theIsoType,
const Standard_Real theParameter)
{
// Initialize data.
Clear();
if (theIsoType == GeomAbs_IsoU || theIsoType == GeomAbs_IsoV) {
const Standard_Boolean isIsoU = (theIsoType == GeomAbs_IsoU);
Handle(TColStd_HArray1OfReal) &aPrm = (isIsoU ? myUPrm : myVPrm);
Handle(TColStd_HArray1OfInteger) &anInd = (isIsoU ? myUInd : myVInd);
Handle(Geom2d_Line) aLine;
aPrm = new TColStd_HArray1OfReal (1, 1);
anInd = new TColStd_HArray1OfInteger(1, 1);
aPrm->SetValue(1, theParameter);
if (isIsoU) {
// U-isoline
gp_Dir2d aDir (0., 1.);
gp_Pnt2d anOri(theParameter, 0.);
aLine = new Geom2d_Line(anOri, aDir);
} else {
// V-isoline
gp_Dir2d aDir (1., 0.);
gp_Pnt2d anOri(0., theParameter);
aLine = new Geom2d_Line(anOri, aDir);
}
Geom2dAdaptor_Curve aGACurve (aLine);
anInd->SetValue(1, myHatcher.AddHatching(aGACurve));
}
}
//=======================================================================
//function : Perform
//purpose :
//=======================================================================
void GEOMUtils::Hatcher::Perform()
{
myHatcher.Trim();
// Compute domains.
Standard_Integer i;
Standard_Integer anIndex;
if (myUInd.IsNull() == Standard_False) {
for (i = myUInd->Lower() ; i <= myUInd->Upper() ; i++) {
anIndex = myUInd->Value(i);
if (anIndex != 0) {
if (myHatcher.TrimDone(anIndex) && !myHatcher.TrimFailed(anIndex)) {
myHatcher.ComputeDomains(anIndex);
if (!myIsDone) {
myIsDone = (myHatcher.NbDomains(anIndex) > 0);
}
}
}
}
}
if (myVInd.IsNull() == Standard_False) {
for (i = myVInd->Lower() ; i <= myVInd->Upper() ; i++) {
anIndex = myVInd->Value(i);
if (anIndex != 0) {
if (myHatcher.TrimDone(anIndex) && !myHatcher.TrimFailed(anIndex)) {
myHatcher.ComputeDomains(anIndex);
if (!myIsDone) {
myIsDone = (myHatcher.NbDomains(anIndex) > 0);
}
}
}
}
}
}
//=======================================================================
//function : GetNbDomains
//purpose :
//=======================================================================
Standard_Integer GEOMUtils::Hatcher::GetNbDomains
(const Standard_Integer theHatchingIndex) const
{
Standard_Integer aResult = -1;
if (myIsDone && myHatcher.IsDone(theHatchingIndex)) {
aResult = myHatcher.NbDomains(theHatchingIndex);
}
return aResult;
}
//=======================================================================
//function : GetDomain
//purpose :
//=======================================================================
Standard_Boolean GEOMUtils::Hatcher::GetDomain
(const Standard_Integer theHatchingIndex,
const Standard_Integer theDomainIndex,
Standard_Real &theParam1,
Standard_Real &theParam2) const
{
Standard_Boolean isOK = Standard_False;
if (theDomainIndex > 0) {
const Standard_Integer aNbDomains = GetNbDomains(theHatchingIndex);
if (theDomainIndex <= aNbDomains) {
const HatchGen_Domain& aDomain =
myHatcher.Domain (theHatchingIndex, theDomainIndex);
if (aDomain.HasFirstPoint()) {
theParam1 = aDomain.FirstPoint().Parameter();
} else {
theParam1 = myVMin - InfiniteValue;
}
if (aDomain.HasSecondPoint()) {
theParam2 = aDomain.SecondPoint().Parameter();
} else {
theParam2 = myVMax + InfiniteValue;
}
isOK = Standard_True;
}
}
return isOK;
}
//=======================================================================
//function : IsDomainInfinite
//purpose :
//=======================================================================
Standard_Boolean GEOMUtils::Hatcher::IsDomainInfinite
(const Standard_Integer theHatchingIndex,
const Standard_Integer theDomainIndex) const
{
Standard_Boolean isInfinite = Standard_False;
if (theDomainIndex > 0) {
const Standard_Integer aNbDomains = GetNbDomains(theHatchingIndex);
if (theDomainIndex <= aNbDomains) {
const HatchGen_Domain& aDomain =
myHatcher.Domain (theHatchingIndex, theDomainIndex);
if (!aDomain.HasFirstPoint() || !aDomain.HasSecondPoint()) {
isInfinite = Standard_True;
}
}
}
return isInfinite;
}
//=======================================================================
//function : GetHatching
//purpose :
//=======================================================================
const Handle(Geom2d_Curve) &GEOMUtils::Hatcher::GetHatching
(const Standard_Integer theHatchingIndex) const
{
const Geom2dAdaptor_Curve &aGACurve =
myHatcher.HatchingCurve(theHatchingIndex);
return aGACurve.Curve();
}
//=======================================================================
//function : Clear
//purpose :
//=======================================================================
void GEOMUtils::Hatcher::Clear()
{
myIsDone = Standard_False;
myUPrm.Nullify();
myVPrm.Nullify();
myUInd.Nullify();
myVInd.Nullify();
myHatcher.ClrHatchings();
}