Loading files
// Created on: 1993-11-04
// Created by: Jean Marc LACHAUME
// 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 <Geom2dAdaptor_Curve.hxx>
#include <Geom2dHatch_Classifier.hxx>
#include <Geom2dHatch_Element.hxx>
#include <Geom2dHatch_Hatcher.hxx>
#include <Geom2dHatch_Hatching.hxx>
#include <Geom2dHatch_Intersector.hxx>
#include <HatchGen_Domain.hxx>
#include <HatchGen_PointOnElement.hxx>
#include <HatchGen_PointOnHatching.hxx>
#include <IntRes2d_IntersectionPoint.hxx>
#include <IntRes2d_IntersectionSegment.hxx>
#include <IntRes2d_Transition.hxx>
#include <Precision.hxx>
#include <StdFail_NotDone.hxx>
#include <TopAbs.hxx>
#include <TopTrans_CurveTransition.hxx>
#define RAISE_IF_NOSUCHOBJECT 0
#define TRACE_HATCHER 0
//=======================================================================
//=======================================================================
// Category : General use.
//=======================================================================
//=======================================================================
//=================================================================================================
Geom2dHatch_Hatcher::Geom2dHatch_Hatcher(const Geom2dHatch_Intersector& Intersector,
const double Confusion2d,
const double Confusion3d,
const bool KeepPnt,
const bool KeepSeg)
: myIntersector(Intersector),
myConfusion2d(Confusion2d),
myConfusion3d(Confusion3d),
myKeepPoints(KeepPnt),
myKeepSegments(KeepSeg),
myNbElements(0),
myNbHatchings(0)
{
}
//=======================================================================
// Function : Intersector
// Purpose : Sets the associated intersector.
//=======================================================================
void Geom2dHatch_Hatcher::Intersector(const Geom2dHatch_Intersector& Intersector)
{
myIntersector = Intersector;
for (int IndH = 1; IndH <= myNbHatchings; IndH++)
{
if (myHatchings.IsBound(IndH))
{
Geom2dHatch_Hatching& Hatching = myHatchings.ChangeFind(IndH);
Hatching.ClrPoints();
}
}
}
//=======================================================================
// Function : Confusion2d
// Purpose : Sets the 2dconfusion tolerance.
//=======================================================================
void Geom2dHatch_Hatcher::Confusion2d(const double Confusion)
{
myConfusion2d = Confusion;
for (int IndH = 1; IndH <= myNbHatchings; IndH++)
{
if (myHatchings.IsBound(IndH))
{
Geom2dHatch_Hatching& Hatching = myHatchings.ChangeFind(IndH);
Hatching.ClrPoints();
}
}
}
//=======================================================================
// Function : Confusion3d
// Purpose : Sets the 3d confusion tolerance.
//=======================================================================
void Geom2dHatch_Hatcher::Confusion3d(const double Confusion)
{
myConfusion3d = Confusion;
for (int IndH = 1; IndH <= myNbHatchings; IndH++)
{
if (myHatchings.IsBound(IndH))
{
Geom2dHatch_Hatching& Hatching = myHatchings.ChangeFind(IndH);
Hatching.ClrPoints();
}
}
}
//=================================================================================================
void Geom2dHatch_Hatcher::KeepPoints(const bool Keep)
{
myKeepPoints = Keep;
for (int IndH = 1; IndH <= myNbHatchings; IndH++)
{
if (myHatchings.IsBound(IndH))
{
Geom2dHatch_Hatching& Hatching = myHatchings.ChangeFind(IndH);
Hatching.ClrDomains();
}
}
}
//=================================================================================================
void Geom2dHatch_Hatcher::KeepSegments(const bool Keep)
{
myKeepSegments = Keep;
for (int IndH = 1; IndH <= myNbHatchings; IndH++)
{
if (myHatchings.IsBound(IndH))
{
Geom2dHatch_Hatching& Hatching = myHatchings.ChangeFind(IndH);
Hatching.ClrDomains();
}
}
}
//=======================================================================
//=======================================================================
// Category : Element.
//=======================================================================
//=======================================================================
//=======================================================================
// Function : AddElement
// Purpose : Adds an element to the Hatcher and returns its index.
//=======================================================================
int Geom2dHatch_Hatcher::AddElement(const Geom2dAdaptor_Curve& Curve,
const TopAbs_Orientation Orientation)
{
int IndE;
for (IndE = 1; IndE <= myNbElements && myElements.IsBound(IndE); IndE++)
{
;
}
if (IndE > myNbElements)
{
myNbElements++;
IndE = myNbElements;
}
Geom2dHatch_Element Element(Curve, Orientation);
myElements.Bind(IndE, Element);
for (int IndH = 1; IndH <= myNbHatchings; IndH++)
{
if (myHatchings.IsBound(IndH))
{
Geom2dHatch_Hatching& Hatching = myHatchings.ChangeFind(IndH);
Hatching.ClrPoints();
}
}
return IndE;
}
//=======================================================================
// Function : RemElement
// Purpose : Removes the IndE-th element from the hatcher.
//=======================================================================
void Geom2dHatch_Hatcher::RemElement(const int IndE)
{
#if RAISE_IF_NOSUCHOBJECT
Standard_NoSuchObject_Raise_if(!myElements.IsBound(IndE), "");
#endif
for (int IndH = 1; IndH <= myNbHatchings; IndH++)
{
if (myHatchings.IsBound(IndH))
{
Geom2dHatch_Hatching& Hatching = myHatchings.ChangeFind(IndH);
bool DomainsToClear = false;
for (int IPntH = Hatching.NbPoints(); IPntH > 0; IPntH--)
{
HatchGen_PointOnHatching PntH = Hatching.ChangePoint(IPntH);
for (int IPntE = PntH.NbPoints(); IPntE > 0; IPntE--)
{
if (PntH.Point(IPntE).Index() == IndE)
{
PntH.RemPoint(IPntE);
DomainsToClear = true;
}
}
if (PntH.NbPoints() == 0)
{
Hatching.RemPoint(IPntH);
}
}
if (DomainsToClear)
{
Hatching.ClrDomains();
}
}
}
myElements.UnBind(IndE);
if (IndE == myNbElements)
{
myNbElements--;
}
}
//=======================================================================
// Function : ClrElements
// Purpose : Removes all the elements from the hatcher.
//=======================================================================
void Geom2dHatch_Hatcher::ClrElements()
{
if (myNbElements != 0)
{
if (myNbHatchings != 0)
{
for (int IndH = 1; IndH <= myNbHatchings; IndH++)
{
if (myHatchings.IsBound(IndH))
{
Geom2dHatch_Hatching& Hatching = myHatchings.ChangeFind(IndH);
Hatching.ClrPoints();
}
}
}
myElements.Clear();
myNbElements = 0;
}
}
//=======================================================================
//=======================================================================
// Category : Hatching.
//=======================================================================
//=======================================================================
//=======================================================================
// Function : AddHatching
// Purpose : Adds a hatching to the hatcher and returns its index.
//=======================================================================
int Geom2dHatch_Hatcher::AddHatching(const Geom2dAdaptor_Curve& Curve)
{
int IndH;
for (IndH = 1; IndH <= myNbHatchings && myHatchings.IsBound(IndH); IndH++)
{
;
}
if (IndH > myNbHatchings)
{
myNbHatchings++;
IndH = myNbHatchings;
}
Geom2dHatch_Hatching Hatching(Curve);
myHatchings.Bind(IndH, Hatching);
return IndH;
}
//=======================================================================
// Function : RemHatching
// Purpose : Removes the IndH-th hatching from the hatcher.
//=======================================================================
void Geom2dHatch_Hatcher::RemHatching(const int IndH)
{
#if RAISE_IF_NOSUCHOBJECT
Standard_NoSuchObject_Raise_if(!myHatchings.IsBound(IndH), "");
#endif
Geom2dHatch_Hatching& Hatching = myHatchings.ChangeFind(IndH);
Hatching.ClrPoints();
myHatchings.UnBind(IndH);
if (IndH == myNbHatchings)
{
myNbHatchings--;
}
}
//=======================================================================
// Function : ClrHatchings
// Purpose : Removes all the hatchings from the hatcher.
//=======================================================================
void Geom2dHatch_Hatcher::ClrHatchings()
{
if (myNbHatchings != 0)
{
for (int IndH = 1; IndH <= myNbHatchings; IndH++)
{
if (myHatchings.IsBound(IndH))
{
Geom2dHatch_Hatching& Hatching = myHatchings.ChangeFind(IndH);
Hatching.ClrPoints();
}
}
myHatchings.Clear();
myNbHatchings = 0;
}
}
//=======================================================================
//=======================================================================
// Category : Computation - Trimming
//=======================================================================
//=======================================================================
//=======================================================================
// Function : Trim
// Purpose : Trims all the hatchings of the hatcher by all the elements
// of the hatcher.
//=======================================================================
void Geom2dHatch_Hatcher::Trim()
{
for (int IndH = 1; IndH <= myNbHatchings; IndH++)
{
if (myHatchings.IsBound(IndH))
{
Trim(IndH);
}
}
}
//=======================================================================
// Function : Trim
// Purpose : Adds a hatching to the hatcher and trims it by the elements
// already given and returns its index.
//=======================================================================
int Geom2dHatch_Hatcher::Trim(const Geom2dAdaptor_Curve& Curve)
{
int IndH = AddHatching(Curve);
Trim(IndH);
return IndH;
}
//=======================================================================
// Function : Trim
// Purpose : Trims the IndH-th hatching by the elements already given.
//=======================================================================
void Geom2dHatch_Hatcher::Trim(const int IndH)
{
#if RAISE_IF_NOSUCHOBJECT
Standard_NoSuchObject_Raise_if(!myHatchings.IsBound(IndH), "");
#endif
Geom2dHatch_Hatching& Hatching = myHatchings.ChangeFind(IndH);
Hatching.ClrPoints();
bool OK, AllOK;
AllOK = true;
for (int IndE = 1; IndE <= myNbElements; IndE++)
{
if (myElements.IsBound(IndE))
{
OK = Trim(IndH, IndE);
AllOK = AllOK && OK;
}
}
Hatching.TrimDone(true);
Hatching.TrimFailed(!AllOK);
if (AllOK)
{
for (int IPnt = 1; IPnt <= Hatching.NbPoints(); IPnt++)
{
HatchGen_PointOnHatching& PntH = Hatching.ChangePoint(IPnt);
OK = GlobalTransition(PntH);
AllOK = AllOK && OK;
}
Hatching.Status(AllOK ? HatchGen_NoProblem : HatchGen_TransitionFailure);
}
}
#if TRACE_HATCHER
//=======================================================================
// Function : IntersectionPointDump
// Purpose : Dump of the intersection point.
//=======================================================================
static void IntersectionPointDump(const IntRes2d_IntersectionPoint& Pnt, const int Index)
{
int SavedPrecision = std::cout.precision();
std::cout.precision(15);
std::cout << "----- IntRes2d:: Point # " << std::setw(3) << Index << " ---------------"
<< std::endl;
std::cout << "-- U: " << Pnt.Value().X() << " V: " << Pnt.Value().Y() << std::endl;
std::cout << "-- Parameter on first : " << Pnt.ParamOnFirst() << std::endl;
std::cout << "-- Position on first : ";
switch (Pnt.TransitionOfFirst().PositionOnCurve())
{
case IntRes2d_Head:
std::cout << "HEAD";
break;
case IntRes2d_Middle:
std::cout << "MIDDLE";
break;
case IntRes2d_End:
std::cout << "END";
break;
}
std::cout << std::endl;
std::cout << "-- IntRes2d:: Transition on first : ";
switch (Pnt.TransitionOfFirst().TransitionType())
{
case IntRes2d_In:
std::cout << "IN";
break;
case IntRes2d_Out:
std::cout << "OUT";
break;
case IntRes2d_Touch:
std::cout << "TOUCH";
break;
case IntRes2d_Undecided:
std::cout << "UNDECIDED";
break;
}
std::cout << std::endl;
if (Pnt.TransitionOfFirst().TransitionType() == IntRes2d_Touch)
{
std::cout << "-- IntRes2d:: Situation on first : ";
switch (Pnt.TransitionOfFirst().Situation())
{
case IntRes2d_Inside:
std::cout << "INSIDE";
break;
case IntRes2d_Outside:
std::cout << "OUTSIDE";
break;
case IntRes2d_Unknown:
std::cout << "UNKNOWN";
break;
}
std::cout << std::endl;
}
std::cout << "--------------------------------------------" << std::endl;
std::cout << "-- Parameter on second : " << Pnt.ParamOnSecond() << std::endl;
std::cout << "-- Position on second : ";
switch (Pnt.TransitionOfSecond().PositionOnCurve())
{
case IntRes2d_Head:
std::cout << "HEAD";
break;
case IntRes2d_Middle:
std::cout << "MIDDLE";
break;
case IntRes2d_End:
std::cout << "END";
break;
}
std::cout << std::endl;
std::cout << "-- IntRes2d:: Transition on second : ";
switch (Pnt.TransitionOfSecond().TransitionType())
{
case IntRes2d_In:
std::cout << "IN";
break;
case IntRes2d_Out:
std::cout << "OUT";
break;
case IntRes2d_Touch:
std::cout << "TOUCH";
break;
case IntRes2d_Undecided:
std::cout << "UNDECIDED";
break;
}
std::cout << std::endl;
if (Pnt.TransitionOfSecond().TransitionType() == IntRes2d_Touch)
{
std::cout << "-- IntRes2d:: Situation on second : ";
switch (Pnt.TransitionOfSecond().Situation())
{
case IntRes2d_Inside:
std::cout << "INSIDE";
break;
case IntRes2d_Outside:
std::cout << "OUTSIDE";
break;
case IntRes2d_Unknown:
std::cout << "UNKNOWN";
break;
}
std::cout << std::endl;
}
std::cout << "--------------------------------------------" << std::endl;
std::cout.precision(SavedPrecision);
}
#endif
//=======================================================================
// Function : Trim
// Purpose : Trims the IndH-th hatching of the hatcher by the IndE th
// element.
//=======================================================================
bool Geom2dHatch_Hatcher::Trim(const int IndH, const int IndE)
{
#if RAISE_IF_NOSUCHOBJECT
Standard_NoSuchObject_Raise_if(!myHatchings.IsBound(IndH), "");
Standard_NoSuchObject_Raise_if(!myElements.IsBound(IndE), "");
#endif
Geom2dHatch_Hatching& Hatching = myHatchings.ChangeFind(IndH);
Geom2dHatch_Element& Element = myElements.ChangeFind(IndE);
Geom2dAdaptor_Curve hatching = Hatching.ChangeCurve();
Geom2dAdaptor_Curve element = Element.ChangeCurve();
myIntersector.Intersect(hatching, element);
#if TRACE_HATCHER
std::cout << "--- Hatcher - Trim:: Hatching # " << std::setw(3);
std::cout << IndH << " with Element # " << std::setw(3);
std::cout << IndE << " ----------" << std::endl;
#endif
if (!myIntersector.IsDone())
{
std::cout << " Intersector -> Done = False ";
return false;
}
#if TRACE_HATCHER
if (myIntersector.IsEmpty())
{
std::cout << "No intersection" << std::endl;
std::cout << "--------------------------------------------------------------------"
<< std::endl;
}
#endif
if (myIntersector.IsEmpty())
{
return true;
}
#if TRACE_HATCHER
std::cout << "Number of intersection points : " << std::setw(3) << (myIntersector.NbPoints())
<< std::endl;
std::cout << "Number of intersection segments : " << std::setw(3) << (myIntersector.NbSegments())
<< std::endl;
#endif
//-----------------------------------------------------------------------
// Traitement des points d intersection.
//-----------------------------------------------------------------------
for (int IPntI = 1; IPntI <= myIntersector.NbPoints(); IPntI++)
{
const IntRes2d_IntersectionPoint& PntI = myIntersector.Point(IPntI);
#if TRACE_HATCHER
IntersectionPointDump(PntI, IPntI);
#endif
HatchGen_PointOnElement PntE(PntI);
PntE.SetIndex(IndE);
HatchGen_PointOnHatching PntH(PntI);
PntH.SetIndex(IndH);
PntH.AddPoint(PntE, myConfusion2d);
Hatching.AddPoint(PntH, myConfusion2d);
}
//-----------------------------------------------------------------------
// Traitement des segments d intersection.
//-----------------------------------------------------------------------
for (int ISeg = 1; ISeg <= myIntersector.NbSegments(); ISeg++)
{
const IntRes2d_IntersectionSegment& Seg = myIntersector.Segment(ISeg);
#if TRACE_HATCHER
std::cout << "----- Segment # " << std::setw(3) << ISeg << " -------------" << std::endl;
#endif
bool FirstPoint = Seg.HasFirstPoint();
bool LastPoint = Seg.HasLastPoint();
//-----------------------------------------------------------------------
// Les deux points peuvent etre confondus.
//-----------------------------------------------------------------------
if (FirstPoint && LastPoint)
{
const IntRes2d_IntersectionPoint& Pnt1 = Seg.FirstPoint();
const IntRes2d_IntersectionPoint& Pnt2 = Seg.LastPoint();
const IntRes2d_Transition& TrsPnt1H = Pnt1.TransitionOfFirst();
const IntRes2d_Transition& TrsPnt1E = Pnt1.TransitionOfSecond();
const IntRes2d_Transition& TrsPnt2H = Pnt2.TransitionOfFirst();
const IntRes2d_Transition& TrsPnt2E = Pnt2.TransitionOfSecond();
IntRes2d_TypeTrans TypePnt1H = TrsPnt1H.TransitionType();
IntRes2d_TypeTrans TypePnt1E = TrsPnt1E.TransitionType();
IntRes2d_TypeTrans TypePnt2H = TrsPnt2H.TransitionType();
IntRes2d_TypeTrans TypePnt2E = TrsPnt2E.TransitionType();
//-----------------------------------------------------------------------
// Les deux points peuvent etre confondus au regard de la precision du
// `hatcher'.
//-----------------------------------------------------------------------
bool Conf2d = std::abs(Pnt1.ParamOnFirst() - Pnt2.ParamOnFirst()) <= myConfusion2d;
//-----------------------------------------------------------------------
// Les deux points peuvent etre `confondus' au regard des intersections.
//-----------------------------------------------------------------------
bool Conf3d = false;
if (!Conf2d)
{
Conf3d = true;
if (Conf3d)
{
Conf3d = TypePnt1H != IntRes2d_Touch && TypePnt1H != IntRes2d_Undecided;
}
if (Conf3d)
{
Conf3d = TypePnt1E != IntRes2d_Touch && TypePnt1E != IntRes2d_Undecided;
}
if (Conf3d)
{
Conf3d = TypePnt2H != IntRes2d_Touch && TypePnt2H != IntRes2d_Undecided;
}
if (Conf3d)
{
Conf3d = TypePnt2E != IntRes2d_Touch && TypePnt2E != IntRes2d_Undecided;
}
if (Conf3d)
{
Conf3d = TypePnt1H == TypePnt2H && TypePnt1E == TypePnt2E;
}
if (Conf3d)
{
Conf3d = Pnt1.Value().Distance(Pnt2.Value()) <= myConfusion3d;
}
}
if (Conf2d || Conf3d)
{
HatchGen_PointOnElement PntE;
PntE.SetIndex(IndE);
PntE.SetParameter((Pnt1.ParamOnSecond() + Pnt2.ParamOnSecond()) / 2.);
switch (TrsPnt1E.PositionOnCurve())
{
case IntRes2d_Head: {
PntE.SetPosition(TopAbs_FORWARD);
break;
}
case IntRes2d_Middle: {
switch (TrsPnt2E.PositionOnCurve())
{
case IntRes2d_Head: {
PntE.SetPosition(TopAbs_FORWARD);
break;
}
case IntRes2d_Middle: {
PntE.SetPosition(TopAbs_INTERNAL);
break;
}
case IntRes2d_End: {
PntE.SetPosition(TopAbs_REVERSED);
break;
}
default: {
break;
}
}
break;
}
case IntRes2d_End: {
PntE.SetPosition(TopAbs_REVERSED);
break;
}
default: {
break;
}
}
PntE.SetIntersectionType((PntE.Position() == TopAbs_INTERNAL) ? HatchGen_TRUE
: HatchGen_TOUCH);
PntE.SetStateBefore((TypePnt1H == IntRes2d_In) ? TopAbs_OUT : TopAbs_IN);
PntE.SetStateAfter((TypePnt2H == IntRes2d_In) ? TopAbs_OUT : TopAbs_IN);
HatchGen_PointOnHatching PntH;
PntH.SetIndex(IndH);
PntH.SetParameter((Pnt1.ParamOnFirst() + Pnt2.ParamOnFirst()) / 2.);
switch (TrsPnt1H.PositionOnCurve())
{
case IntRes2d_Head: {
PntH.SetPosition(TopAbs_FORWARD);
break;
}
case IntRes2d_Middle: {
switch (TrsPnt2H.PositionOnCurve())
{
case IntRes2d_Head: {
PntH.SetPosition(TopAbs_FORWARD);
break;
}
case IntRes2d_Middle: {
PntH.SetPosition(TopAbs_INTERNAL);
break;
}
case IntRes2d_End: {
PntH.SetPosition(TopAbs_REVERSED);
break;
}
default: {
break;
}
}
break;
}
case IntRes2d_End: {
PntH.SetPosition(TopAbs_REVERSED);
break;
}
default: {
break;
}
}
PntH.AddPoint(PntE, myConfusion2d);
Hatching.AddPoint(PntH, myConfusion2d);
#if TRACE_HATCHER
IntersectionPointDump(Pnt1, 1);
IntersectionPointDump(Pnt2, 2);
std::cout << "THESE TWO POINTS ARE " << (Conf2d ? "2D" : "3D")
<< " CONFUSED INTO THE FOLLOWING" << std::endl;
PntH.Dump();
#endif
continue;
}
//-----------------------------------------------------------------------
// Traitement du premier point du segment.
//-----------------------------------------------------------------------
if (FirstPoint)
{
const IntRes2d_IntersectionPoint& PntI = Seg.FirstPoint();
#if TRACE_HATCHER
IntersectionPointDump(PntI, 1);
#endif
HatchGen_PointOnElement PntE(PntI);
PntE.SetIndex(IndE);
PntE.SetSegmentBeginning(true);
PntE.SetSegmentEnd(false);
HatchGen_PointOnHatching PntH(PntI);
PntH.SetIndex(IndH);
PntH.AddPoint(PntE, myConfusion2d);
Hatching.AddPoint(PntH, myConfusion2d);
#if TRACE_HATCHER
}
else
{
std::cout << "----- Has no first point --------" << std::endl;
std::cout << "---------------------------------" << std::endl;
#endif
}
//-----------------------------------------------------------------------
// Traitement du deuxieme point du segment.
//-----------------------------------------------------------------------
if (LastPoint)
{
const IntRes2d_IntersectionPoint& PntI = Seg.LastPoint();
#if TRACE_HATCHER
IntersectionPointDump(PntI, 2);
#endif
HatchGen_PointOnElement PntE(PntI);
PntE.SetIndex(IndE);
PntE.SetSegmentBeginning(false);
PntE.SetSegmentEnd(true);
HatchGen_PointOnHatching PntH(PntI);
PntH.SetIndex(IndH);
PntH.AddPoint(PntE, myConfusion2d);
Hatching.AddPoint(PntH, myConfusion2d);
#if TRACE_HATCHER
}
else
{
std::cout << "----- Has no last point ---------" << std::endl;
std::cout << "---------------------------------" << std::endl;
#endif
}
}
#if TRACE_HATCHER
std::cout << "--------------------------------------------------------------------"
<< std::endl;
#endif
}
return true;
}
//=======================================================================
//=======================================================================
// Category : Computation - Domains
//=======================================================================
//=======================================================================
//=======================================================================
// Function : GlobalTransition
// Purpose : Returns the before and after states of the complex
// transition of the IndP-th intersection point of the
// IndH-th hatching.
//=======================================================================
bool Geom2dHatch_Hatcher::GlobalTransition(HatchGen_PointOnHatching& Point)
{
TopAbs_State StateBefore = TopAbs_UNKNOWN;
TopAbs_State StateAfter = TopAbs_UNKNOWN;
bool SegmentBegin = false;
bool SegmentEnd = false;
gp_Dir2d Tangente2d, Normale2d;
gp_Dir Tangente, Normale;
double Courbure;
const Geom2dAdaptor_Curve& CurveH = HatchingCurve(Point.Index());
myIntersector.LocalGeometry(CurveH.Curve(), Point.Parameter(), Tangente2d, Normale2d, Courbure);
Tangente.SetCoord(Tangente2d.X(), Tangente2d.Y(), 0.0);
if (Courbure < Precision::Confusion())
{
Normale.SetCoord(-Tangente2d.Y(), Tangente2d.X(), 0.0);
}
else
{
Normale.SetCoord(Normale2d.X(), Normale2d.Y(), 0.0);
}
TopTrans_CurveTransition ComplexTransition;
ComplexTransition.Reset(Tangente, Normale, Courbure);
#if TRACE_HATCHER
printf("\n ----- Global Transition Complex Transition Reset \n");
printf("\n P:%+10.5g Tg2d:%+10.5g , %+10.5g N2d:%+10.5g , %+10.5g Crv:%+10.5g\n\n",
Point.Parameter(),
Tangente.X(),
Tangente.Y(),
Normale.X(),
Normale.Y(),
Courbure);
#endif
for (int IPntE = 1; IPntE <= Point.NbPoints(); IPntE++)
{
const HatchGen_PointOnElement& PntE = Point.Point(IPntE);
SegmentBegin = SegmentBegin || PntE.SegmentBeginning();
SegmentEnd = SegmentEnd || PntE.SegmentEnd();
const Geom2dHatch_Element& Element = myElements.Find(PntE.Index());
const Geom2dAdaptor_Curve& CurveE = Element.Curve();
TopAbs_Orientation ElementOrientation = Element.Orientation();
bool ToReverse = (ElementOrientation == TopAbs_REVERSED);
double Param;
switch (PntE.Position())
{
case TopAbs_FORWARD:
Param = ToReverse ? CurveE.LastParameter() : CurveE.FirstParameter();
break;
case TopAbs_INTERNAL:
Param = PntE.Parameter();
break;
case TopAbs_REVERSED:
Param = ToReverse ? CurveE.FirstParameter() : CurveE.LastParameter();
break;
default:
break;
}
//--
#if TRACE_HATCHER
printf("\n ******** ToReverse: %d Param : %g ANParam : %g \n",
ToReverse,
Param,
PntE.Parameter());
#endif
// TODO: finding #25 - this overwrites Param computed by the switch above,
// making the position-based logic dead code. Removing this line caused
// blend regressions. The switch logic may need endpoint-specific investigation.
Param = PntE.Parameter();
myIntersector.LocalGeometry(CurveE.Curve(), Param, Tangente2d, Normale2d, Courbure);
//-----------------------------------------------------------------------
// Calcul de la transition locale. On suppose les relations suivantes :
// - Si l orientation de l element est INTERNAL ==> INTERNAL
// - Si l orientation de l element est EXTERNAL ==> EXTERNAL
// - Si tangence, on a IN-IN ou OUT-OUT ==> INTERNAL/EXTERNAL
// - Sinon, on a IN-OUT ou OUT-IN ==> REVERSED/FORWARD
// Les deux dernieres conditions avec l element vu en FORWARD.
//-----------------------------------------------------------------------
TopAbs_Orientation LocalTransition = TopAbs_EXTERNAL;
if (ElementOrientation == TopAbs_INTERNAL)
{
LocalTransition = TopAbs_INTERNAL;
}
else if (ElementOrientation == TopAbs_EXTERNAL)
{
LocalTransition = TopAbs_EXTERNAL;
}
else if (PntE.IntersectionType() == HatchGen_TANGENT)
{
if (PntE.Position() == TopAbs_INTERNAL)
{
switch (PntE.StateBefore())
{
case TopAbs_IN:
LocalTransition = ToReverse ? TopAbs_EXTERNAL : TopAbs_INTERNAL;
break;
case TopAbs_OUT:
LocalTransition = ToReverse ? TopAbs_INTERNAL : TopAbs_EXTERNAL;
break;
default:
break;
}
}
else
{
switch (PntE.StateBefore())
{
case TopAbs_IN:
LocalTransition = ToReverse ? TopAbs_FORWARD : TopAbs_REVERSED;
break;
case TopAbs_OUT:
LocalTransition = ToReverse ? TopAbs_REVERSED : TopAbs_FORWARD;
break;
default:
break;
}
}
}
else
{
switch (PntE.StateBefore())
{
case TopAbs_IN:
LocalTransition = ToReverse ? TopAbs_FORWARD : TopAbs_REVERSED;
break;
case TopAbs_OUT:
LocalTransition = ToReverse ? TopAbs_REVERSED : TopAbs_FORWARD;
break;
default:
break;
}
}
//-----------------------------------------------------------------------
// Orientation de la tangente au point d interference.
//-----------------------------------------------------------------------
TopAbs_Orientation TangenteOrientation = TopAbs_FORWARD;
switch (PntE.Position())
{
case TopAbs_FORWARD:
TangenteOrientation = ToReverse ? TopAbs_REVERSED : TopAbs_FORWARD;
break;
case TopAbs_INTERNAL:
TangenteOrientation = TopAbs_INTERNAL;
break;
case TopAbs_REVERSED:
TangenteOrientation = ToReverse ? TopAbs_FORWARD : TopAbs_REVERSED;
break;
default:
break;
}
//-----------------------------------------------------------------------
// Proprietes geometriques.
//-----------------------------------------------------------------------
if (ToReverse)
{
Tangente.SetCoord(-Tangente2d.X(), -Tangente2d.Y(), 0.0);
}
else
{
Tangente.SetCoord(Tangente2d.X(), Tangente2d.Y(), 0.0);
}
Normale.SetCoord(Normale2d.X(), Normale2d.Y(), 0.0);
#if TRACE_HATCHER
printf("\n \n----- Global Transition Complex Transition Compare");
char* str1 = " ??? ";
char* str2 = " ??? ";
if (LocalTransition == TopAbs_INTERNAL)
str1 = " INTERNAL ";
if (LocalTransition == TopAbs_REVERSED)
str1 = " REVERSED ";
if (LocalTransition == TopAbs_FORWARD)
str1 = " FORWARD ";
if (TangenteOrientation == TopAbs_INTERNAL)
str2 = " INTERNAL ";
if (TangenteOrientation == TopAbs_REVERSED)
str2 = " REVERSED ";
if (TangenteOrientation == TopAbs_FORWARD)
str2 = " FORWARD ";
printf("\n P:%+10.5g Tg2d:%+10.5g , %+10.5g N2d:%+10.5g , %+10.5g Crv:%+10.5g "
"LocalTr:%s TangOrie:%s\n",
Param,
Tangente.X(),
Tangente.Y(),
Normale.X(),
Normale.Y(),
Courbure,
str1,
str2);
#endif
ComplexTransition.Compare(Precision::Angular(),
Tangente,
Normale,
Courbure,
LocalTransition,
TangenteOrientation);
}
switch (ComplexTransition.StateBefore())
{
case TopAbs_IN:
StateBefore = TopAbs_IN;
break;
case TopAbs_OUT:
StateBefore = TopAbs_OUT;
break;
case TopAbs_ON:
return false;
case TopAbs_UNKNOWN:
return false;
}
switch (ComplexTransition.StateAfter())
{
case TopAbs_IN:
StateAfter = TopAbs_IN;
break;
case TopAbs_OUT:
StateAfter = TopAbs_OUT;
break;
case TopAbs_ON:
return false;
case TopAbs_UNKNOWN:
return false;
}
#if TRACE_HATCHER
printf("\n");
printf("\n --> StateBef :");
if (StateBefore == TopAbs_IN)
printf(" IN ");
else
printf(" OUT ");
printf("\n --> StateAft :");
if (StateAfter == TopAbs_IN)
printf(" IN ");
else
printf(" OUT ");
printf("\n------ Fin GlobalTransition\n");
#endif
Point.SetStateBefore(StateBefore);
Point.SetStateAfter(StateAfter);
Point.SetSegmentBeginning(SegmentBegin);
Point.SetSegmentEnd(SegmentEnd);
return true;
}
//=======================================================================
// Function : ComputeDomains
// Purpose : Computes the domains of all the hatchings.
//=======================================================================
void Geom2dHatch_Hatcher::ComputeDomains()
{
for (int IndH = 1; IndH <= myNbHatchings; IndH++)
{
if (myHatchings.IsBound(IndH))
{
ComputeDomains(IndH);
}
}
}
//=======================================================================
// Function : ComputeDomains
// Purpose : Computes the domains of the IndH-th hatching.
//=======================================================================
void Geom2dHatch_Hatcher::ComputeDomains(const int IndH)
{
#if RAISE_IF_NOSUCHOBJECT
Standard_NoSuchObject_Raise_if(!myHatchings.IsBound(IndH), "");
#endif
Geom2dHatch_Hatching& Hatching = myHatchings.ChangeFind(IndH);
Hatching.ClrDomains();
Hatching.IsDone(false);
if (!Hatching.TrimDone())
{
Trim(IndH);
}
if (Hatching.Status() != HatchGen_NoProblem)
{
return;
}
bool Points = myKeepPoints;
bool Segments = myKeepSegments;
int ISav = 0;
bool SavPnt = false;
int NbOpenedSegments = 0;
int NbPnt = Hatching.NbPoints();
int IPnt = 1;
if (NbPnt == 0)
{
//-- std::cout << "The hatching # " << std::setw(3) << IndH << " has to be classified" <<
// std::endl ;
Geom2dHatch_Classifier Classifier(myElements, Hatching.ClassificationPoint(), 0.0000001);
if (Classifier.State() == TopAbs_IN)
{
HatchGen_Domain domain;
Hatching.AddDomain(domain);
}
Hatching.IsDone(true);
return;
}
// for (int IPnt = 1 ; IPnt <= NbPnt ; IPnt++) {
for (IPnt = 1; IPnt <= NbPnt; IPnt++)
{
bool NoDomain = Hatching.NbDomains() == 0;
bool FirstPoint = IPnt == 1;
bool LastPoint = IPnt == NbPnt;
const HatchGen_PointOnHatching& CurPnt = Hatching.Point(IPnt);
#if TRACE_HATCHER
std::cout << "===== ComputeDomains:: Hatching # " << std::setw(3) << IndH
<< " =====" << std::endl;
CurPnt.Dump(IPnt);
std::cout << "==========================================" << std::endl;
#endif
//-----------------------------------------------------------------------
// Calcul des domaines.
//-----------------------------------------------------------------------
TopAbs_State StateBefore = CurPnt.StateBefore();
TopAbs_State StateAfter = CurPnt.StateAfter();
bool SegmentBegin = CurPnt.SegmentBeginning();
bool SegmentEnd = CurPnt.SegmentEnd();
HatchGen_Domain domain;
//-----------------------------------------------------------------------
// Initialisations dues au premier point.
//-----------------------------------------------------------------------
if (FirstPoint)
{
SavPnt = false;
ISav = 0;
NbOpenedSegments = 0;
if (SegmentEnd && SegmentBegin)
{
if (StateAfter == TopAbs_UNKNOWN)
{
StateAfter = TopAbs_IN;
}
if (StateBefore == TopAbs_UNKNOWN)
{
StateBefore = TopAbs_IN;
}
if (Segments)
{
SavPnt = true;
ISav = 0;
}
}
else if (SegmentEnd)
{
if (StateAfter == TopAbs_UNKNOWN)
{
StateAfter = TopAbs_IN;
}
if (Segments)
{
SavPnt = true;
ISav = 0;
}
}
else if (SegmentBegin)
{
if (StateBefore == TopAbs_UNKNOWN)
{
StateBefore = TopAbs_IN;
}
if (StateBefore == TopAbs_IN)
{
SavPnt = true;
ISav = 0;
}
}
else
{
if (StateBefore == TopAbs_IN)
{
SavPnt = true;
ISav = 0;
}
}
}
//-----------------------------------------------------------------------
// Initialisations dues au dernier point.
//-----------------------------------------------------------------------
if (LastPoint)
{
if (SegmentEnd && SegmentBegin)
{
if (StateAfter == TopAbs_UNKNOWN)
{
StateAfter = TopAbs_IN;
}
if (StateBefore == TopAbs_UNKNOWN)
{
StateBefore = TopAbs_IN;
}
}
else if (SegmentEnd)
{
if (StateAfter == TopAbs_UNKNOWN)
{
StateAfter = TopAbs_IN;
}
}
else if (SegmentBegin)
{
if (StateBefore == TopAbs_UNKNOWN)
{
StateBefore = TopAbs_IN;
}
}
else
{
}
}
//-----------------------------------------------------------------------
// Cas general.
//-----------------------------------------------------------------------
bool ToAppend = false;
if (SegmentEnd && SegmentBegin)
{
if (StateBefore != TopAbs_IN && StateAfter != TopAbs_IN)
{
Hatching.Status(HatchGen_IncompatibleStates);
return;
}
if (Points)
{
if (Segments)
{
if (!SavPnt)
{
if (NoDomain)
{
Hatching.Status(HatchGen_IncoherentParity);
}
else
{
Hatching.IsDone(true);
}
return;
}
if (ISav != 0)
{
domain.SetFirstPoint(Hatching.Point(ISav));
}
domain.SetSecondPoint(CurPnt);
ToAppend = true;
SavPnt = true;
ISav = IPnt;
}
else
{
bool isININ = (StateBefore == TopAbs_IN && StateAfter == TopAbs_IN);
if (SavPnt && !isININ)
{
if (NoDomain)
{
Hatching.Status(HatchGen_IncoherentParity);
}
else
{
Hatching.IsDone(true);
}
return;
}
domain.SetPoints(CurPnt, CurPnt);
ToAppend = true;
SavPnt = false;
ISav = 0;
}
}
}
else if (SegmentEnd)
{
if (Segments)
{
if (StateAfter == TopAbs_OUT)
{
if (!SavPnt)
{
if (NoDomain)
{
Hatching.Status(HatchGen_IncoherentParity);
}
else
{
Hatching.IsDone(true);
}
return;
}
if (ISav != 0)
{
domain.SetFirstPoint(Hatching.Point(ISav));
}
domain.SetSecondPoint(CurPnt);
ToAppend = true;
}
else
{
if (Points)
{
if (ISav != 0)
{
domain.SetFirstPoint(Hatching.Point(ISav));
}
domain.SetSecondPoint(CurPnt);
ToAppend = true;
SavPnt = true;
ISav = IPnt;
}
}
}
else
{
if (StateAfter == TopAbs_IN)
{
SavPnt = true;
ISav = IPnt;
}
}
NbOpenedSegments--;
}
else if (SegmentBegin)
{
if (Segments)
{
if (StateBefore == TopAbs_OUT)
{
SavPnt = true;
ISav = IPnt;
}
else
{
if (Points)
{
if (!SavPnt)
{
if (NoDomain)
{
Hatching.Status(HatchGen_IncoherentParity);
}
else
{
Hatching.IsDone(true);
}
return;
}
if (ISav != 0)
{
domain.SetFirstPoint(Hatching.Point(ISav));
}
domain.SetSecondPoint(CurPnt);
ToAppend = true;
SavPnt = true;
ISav = IPnt;
}
}
}
else
{
if (StateBefore == TopAbs_IN)
{
if (!SavPnt)
{
if (NoDomain)
{
Hatching.Status(HatchGen_IncoherentParity);
}
else
{
Hatching.IsDone(true);
}
return;
}
if (ISav != 0)
{
domain.SetFirstPoint(Hatching.Point(ISav));
}
domain.SetSecondPoint(CurPnt);
ToAppend = true;
// Modified by Sergey KHROMOV - Fri Jan 5 12:05:30 2001
// SavPnt = false ;
// ISav = 0 ;
SavPnt = true;
ISav = IPnt;
// Modified by Sergey KHROMOV - Fri Jan 5 12:05:31 2001
}
}
NbOpenedSegments++;
}
else
{
//-- ???????????????????????????????????????????????????????????????????????????
//-- Solution provisoire (lbr le 11 Aout 97 )
//-- si On a 2 points dont des points OUT OUT ou IN IN qui delimitent une isos
//-- on transforme les transitions
if (StateBefore == TopAbs_OUT && StateAfter == TopAbs_OUT)
{
if (NbPnt == 2)
{
if (FirstPoint)
{
StateAfter = TopAbs_IN;
}
else
{
StateBefore = TopAbs_IN;
}
}
}
//-- ???????????????????????????????????????????????????????????????????????????
if (StateBefore == TopAbs_OUT && StateAfter == TopAbs_OUT)
{
if (SavPnt)
{
if (NoDomain)
{
Hatching.Status(HatchGen_IncoherentParity);
}
else
{
Hatching.IsDone(true);
}
return;
}
if (Points)
{
domain.SetPoints(CurPnt, CurPnt);
ToAppend = true;
SavPnt = true;
ISav = IPnt;
}
}
else if (StateBefore == TopAbs_OUT && StateAfter == TopAbs_IN)
{
SavPnt = true;
ISav = IPnt;
}
else if (StateBefore == TopAbs_IN && StateAfter == TopAbs_OUT)
{
if (!SavPnt)
{
if (NoDomain)
{
Hatching.Status(HatchGen_IncoherentParity);
}
else
{
Hatching.IsDone(true);
}
return;
}
if (ISav != 0)
{
domain.SetFirstPoint(Hatching.Point(ISav));
}
domain.SetSecondPoint(CurPnt);
ToAppend = true;
SavPnt = false;
ISav = 0;
}
else if (StateBefore == TopAbs_IN && StateAfter == TopAbs_IN)
{
if (Points)
{
if (NbOpenedSegments == 0)
{
if (!SavPnt)
{
if (NoDomain)
{
Hatching.Status(HatchGen_IncoherentParity);
}
else
{
Hatching.IsDone(true);
}
// return;
continue;
}
if (ISav != 0)
{
domain.SetFirstPoint(Hatching.Point(ISav));
}
domain.SetSecondPoint(CurPnt);
ToAppend = true;
SavPnt = true;
ISav = IPnt;
}
else
{
if (Segments)
{
if (!SavPnt)
{
if (NoDomain)
{
Hatching.Status(HatchGen_IncoherentParity);
}
else
{
Hatching.IsDone(true);
}
return;
}
if (ISav != 0)
{
domain.SetFirstPoint(Hatching.Point(ISav));
}
domain.SetSecondPoint(CurPnt);
ToAppend = true;
SavPnt = true;
ISav = IPnt;
}
else
{
if (SavPnt)
{
if (NoDomain)
{
Hatching.Status(HatchGen_IncoherentParity);
}
else
{
Hatching.IsDone(true);
}
return;
}
domain.SetPoints(CurPnt, CurPnt);
ToAppend = true;
SavPnt = false;
ISav = 0;
}
}
}
}
else
{
Hatching.Status(HatchGen_IncompatibleStates);
return;
}
}
//-----------------------------------------------------------------------
// Ajout du domaine.
//-----------------------------------------------------------------------
if (ToAppend)
{
Hatching.AddDomain(domain);
}
//-----------------------------------------------------------------------
// Traitement lie au dernier point.
//-----------------------------------------------------------------------
if (LastPoint)
{
domain.SetPoints();
ToAppend = false;
if (SegmentEnd && SegmentBegin)
{
if (Segments)
{
if (!SavPnt)
{
if (NoDomain)
{
Hatching.Status(HatchGen_IncoherentParity);
}
else
{
Hatching.IsDone(true);
}
return;
}
if (ISav != 0)
{
domain.SetFirstPoint(Hatching.Point(ISav));
}
ToAppend = true;
}
}
else if (SegmentEnd)
{
if (StateAfter == TopAbs_IN)
{
if (!SavPnt)
{
if (NoDomain)
{
Hatching.Status(HatchGen_IncoherentParity);
}
else
{
Hatching.IsDone(true);
}
return;
}
if (ISav != 0)
{
domain.SetFirstPoint(Hatching.Point(ISav));
}
ToAppend = true;
}
}
else if (SegmentBegin)
{
if (Segments)
{
if (!SavPnt)
{
if (NoDomain)
{
Hatching.Status(HatchGen_IncoherentParity);
}
else
{
Hatching.IsDone(true);
}
return;
}
if (ISav != 0)
{
domain.SetFirstPoint(Hatching.Point(ISav));
}
ToAppend = true;
}
}
else
{
if (StateAfter == TopAbs_IN)
{
if (!SavPnt)
{
if (NoDomain)
{
Hatching.Status(HatchGen_IncoherentParity);
}
else
{
Hatching.IsDone(true);
}
return;
}
if (ISav != 0)
{
domain.SetFirstPoint(Hatching.Point(ISav));
}
ToAppend = true;
}
}
if (ToAppend)
{
Hatching.AddDomain(domain);
}
}
}
Hatching.IsDone(true);
}
//=======================================================================
//=======================================================================
// Category : Results.
//=======================================================================
//=======================================================================
//=======================================================================
// Function : Domain
// Purpose : Returns the IDom-th domain of the IndH-th hatching.
//=======================================================================
const HatchGen_Domain& Geom2dHatch_Hatcher::Domain(const int IndH, const int IDom) const
{
#if RAISE_IF_NOSUCHOBJECT
Standard_NoSuchObject_Raise_if(!myHatchings.IsBound(IndH), "");
#endif
const Geom2dHatch_Hatching& Hatching = myHatchings.Find(IndH);
StdFail_NotDone_Raise_if(!Hatching.IsDone(), "Geom2dHatch_Hatcher::Domain");
#if RAISE_IF_NOSUCHOBJECT
Standard_OutOfRange_Raise_if(IDom < 1 || IDom > Hatching.NbDomains(), "");
#endif
const HatchGen_Domain& Domain = Hatching.Domain(IDom);
return Domain;
}
//=======================================================================
//=======================================================================
// Category : Dump.
//=======================================================================
//=======================================================================
//=================================================================================================
void Geom2dHatch_Hatcher::Dump() const
{
std::cout << '\n';
std::cout << "========================================================" << '\n';
std::cout << "=== Dump of the hatcher ================================" << '\n';
std::cout << "========================================================" << '\n';
std::cout << '\n';
std::cout << "The points are " << (myKeepPoints ? " " : "not ") << "considered." << '\n';
std::cout << "The segments are " << (myKeepSegments ? " " : "not ") << "considered." << '\n';
std::cout << "2D Confusion tolerance : " << myConfusion2d << '\n';
std::cout << "3D Confusion tolerance : " << myConfusion3d << '\n';
std::cout << myNbHatchings << " hatching" << ((myNbHatchings == 1) ? "" : "s") << '\n';
std::cout << myNbElements << " element" << ((myNbElements == 1) ? "" : "s") << '\n';
std::cout << '\n';
std::cout << "========================================================" << '\n';
std::cout << "=== Hatchings ==========================================" << '\n';
std::cout << "========================================================" << '\n';
std::cout << '\n';
for (int IndH = 1; IndH <= myNbHatchings; IndH++)
{
std::cout << "Hatching # " << IndH;
if (!myHatchings.IsBound(IndH))
{
std::cout << " is not bound" << '\n';
}
else
{
const Geom2dHatch_Hatching& Hatching = myHatchings.Find(IndH);
int NbPnt = Hatching.NbPoints();
std::cout << " contains " << NbPnt << " restriction points :" << '\n';
for (int IPnt = 1; IPnt <= NbPnt; IPnt++)
{
const HatchGen_PointOnHatching& PntH = Hatching.Point(IPnt);
PntH.Dump(IPnt);
}
std::cout << "----------------------------------------------" << '\n';
}
}
std::cout << '\n';
std::cout << "========================================================" << '\n';
std::cout << "=== Elements ===========================================" << '\n';
std::cout << "========================================================" << '\n';
std::cout << '\n';
for (int IndE = 1; IndE <= myNbElements; IndE++)
{
std::cout << "Element # " << IndE;
if (!myElements.IsBound(IndE))
{
std::cout << " is not bound" << '\n';
}
else
{
const Geom2dHatch_Element& Element = myElements.Find(IndE);
switch (Element.Orientation())
{
case TopAbs_FORWARD:
std::cout << " is FORWARD" << '\n';
break;
case TopAbs_REVERSED:
std::cout << " is REVERSED" << '\n';
break;
case TopAbs_INTERNAL:
std::cout << " is INTERNAL" << '\n';
break;
case TopAbs_EXTERNAL:
std::cout << " is EXTERNAL" << '\n';
break;
}
}
}
std::cout << '\n';
}
3d097a032This file is pinned to the selected release. Download the original to open it in your design tool.