Loading files
3d097a032This file is pinned to the selected release. Download the original to open it in your design tool.
// Created on: 1997-04-17
// Created by: Christophe MARION
// Copyright (c) 1997-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.
#ifndef No_Exception
#define No_Exception
#endif
#include <HLRAlgo_Intersection.hxx>
#include <HLRBRep_AreaLimit.hxx>
#include <HLRBRep_EdgeBuilder.hxx>
#include <HLRBRep_VertexList.hxx>
#include <Standard_DomainError.hxx>
#include <Standard_NoMoreObject.hxx>
#include <Standard_NoSuchObject.hxx>
#include <TopAbs.hxx>
//=================================================================================================
HLRBRep_EdgeBuilder::HLRBRep_EdgeBuilder(HLRBRep_VertexList& VList)
{
// at creation the EdgeBuilder explore the VertexList
// and use it to build a list of "AreaLimit" on the edge.
// An area is a part of the curve between
// two consecutive vertices
Standard_DomainError_Raise_if(!VList.More(), "EdgeBuilder : Empty vertex list");
occ::handle<HLRBRep_AreaLimit> last, cur;
TopAbs_State before, after, ebefore, eafter;
HLRAlgo_Intersection V;
// loop on the Vertices
for (; VList.More(); VList.Next())
{
before = after = ebefore = eafter = TopAbs_UNKNOWN;
// compute the states
if (VList.IsBoundary())
{
switch (VList.Orientation())
{
case TopAbs_FORWARD:
ebefore = TopAbs_OUT;
eafter = TopAbs_IN;
break;
case TopAbs_REVERSED:
ebefore = TopAbs_IN;
eafter = TopAbs_OUT;
break;
case TopAbs_INTERNAL:
ebefore = TopAbs_IN;
eafter = TopAbs_IN;
break;
case TopAbs_EXTERNAL:
ebefore = TopAbs_OUT;
eafter = TopAbs_OUT;
break;
}
}
if (VList.IsInterference())
{
switch (VList.Transition())
{
case TopAbs_FORWARD:
before = TopAbs_OUT;
after = TopAbs_IN;
break;
case TopAbs_REVERSED:
before = TopAbs_IN;
after = TopAbs_OUT;
break;
case TopAbs_INTERNAL:
before = TopAbs_IN;
after = TopAbs_IN;
break;
case TopAbs_EXTERNAL:
before = TopAbs_OUT;
after = TopAbs_OUT;
break;
}
switch (VList.BoundaryTransition())
{
case TopAbs_FORWARD:
after = TopAbs_ON;
break;
case TopAbs_REVERSED:
before = TopAbs_ON;
break;
case TopAbs_INTERNAL:
before = TopAbs_ON;
after = TopAbs_ON;
break;
case TopAbs_EXTERNAL:
break;
}
}
// create the Limit and connect to list
V = VList.Current();
cur = new HLRBRep_AreaLimit(V,
VList.IsBoundary(),
VList.IsInterference(),
before,
after,
ebefore,
eafter);
if (myLimits.IsNull())
{
myLimits = cur;
last = cur;
}
else
{
last->Next(cur);
cur->Previous(last);
last = cur;
}
}
// periodicity, make a circular list
if (VList.IsPeriodic())
{
last->Next(myLimits);
myLimits->Previous(last);
}
// process UNKNOWN areas
TopAbs_State stat = TopAbs_UNKNOWN;
TopAbs_State estat = TopAbs_UNKNOWN;
cur = myLimits;
while (!cur.IsNull())
{
if (stat == TopAbs_UNKNOWN)
{
stat = cur->StateBefore();
if (stat == TopAbs_UNKNOWN)
{
stat = cur->StateAfter();
}
}
if (estat == TopAbs_UNKNOWN)
{
estat = cur->EdgeBefore();
if (estat == TopAbs_UNKNOWN)
{
estat = cur->EdgeAfter();
}
}
cur = cur->Next();
// test for periodicicity
if (cur == myLimits)
{
break;
}
}
// error if no interferences
Standard_DomainError_Raise_if(stat == TopAbs_UNKNOWN, "EdgeBuilder : No interferences");
// if no boundary the edge covers the whole curve
if (estat == TopAbs_UNKNOWN)
{
estat = TopAbs_IN;
}
// propagate states
cur = myLimits;
while (!cur.IsNull())
{
if (cur->StateBefore() == TopAbs_UNKNOWN)
{
cur->StateBefore(stat);
}
else
{
stat = cur->StateAfter();
}
if (cur->StateAfter() == TopAbs_UNKNOWN)
{
cur->StateAfter(stat);
}
if (cur->EdgeBefore() == TopAbs_UNKNOWN)
{
cur->EdgeBefore(estat);
}
else
{
estat = cur->EdgeAfter();
}
if (cur->EdgeAfter() == TopAbs_UNKNOWN)
{
cur->EdgeAfter(estat);
}
cur = cur->Next();
if (cur == myLimits)
{
break;
}
}
// initialise with IN parts
Builds(TopAbs_IN);
}
//=================================================================================================
void HLRBRep_EdgeBuilder::InitAreas()
{
left = myLimits->Previous();
right = myLimits;
}
//=================================================================================================
void HLRBRep_EdgeBuilder::NextArea()
{
left = right;
if (!right.IsNull())
{
right = right->Next();
}
}
//=================================================================================================
void HLRBRep_EdgeBuilder::PreviousArea()
{
right = left;
if (!left.IsNull())
{
left = left->Previous();
}
}
//=================================================================================================
bool HLRBRep_EdgeBuilder::HasArea() const
{
if (left.IsNull())
{
if (right.IsNull())
{
return false;
}
}
if (right == myLimits)
{
return false;
}
return true;
}
//=================================================================================================
TopAbs_State HLRBRep_EdgeBuilder::AreaState() const
{
TopAbs_State stat = TopAbs_UNKNOWN;
if (!left.IsNull())
{
stat = left->StateAfter();
}
if (!right.IsNull())
{
stat = right->StateBefore();
}
return stat;
}
//=================================================================================================
TopAbs_State HLRBRep_EdgeBuilder::AreaEdgeState() const
{
TopAbs_State stat = TopAbs_UNKNOWN;
if (!left.IsNull())
{
stat = left->EdgeAfter();
}
if (!right.IsNull())
{
stat = right->EdgeBefore();
}
return stat;
}
//=================================================================================================
occ::handle<HLRBRep_AreaLimit> HLRBRep_EdgeBuilder::LeftLimit() const
{
return left;
}
//=================================================================================================
occ::handle<HLRBRep_AreaLimit> HLRBRep_EdgeBuilder::RightLimit() const
{
return right;
}
//=================================================================================================
void HLRBRep_EdgeBuilder::Builds(const TopAbs_State ToBuild)
{
toBuild = ToBuild;
InitAreas();
do
{
if ((AreaState() == toBuild) && (AreaEdgeState() == TopAbs_IN))
{
if (left.IsNull())
{
current = 2;
}
else
{
current = 1;
}
return;
}
NextArea();
} while (HasArea());
current = 3;
}
//=================================================================================================
bool HLRBRep_EdgeBuilder::MoreEdges() const
{
return HasArea();
}
//=================================================================================================
void HLRBRep_EdgeBuilder::NextEdge()
{
// clean the current edge
while (AreaState() == toBuild)
{
NextArea();
}
// go to the next edge
while (HasArea())
{
if ((AreaState() == toBuild) && (AreaEdgeState() == TopAbs_IN))
{
if (left.IsNull())
{
current = 2;
}
else
{
current = 1;
}
return;
}
NextArea();
}
}
//=================================================================================================
bool HLRBRep_EdgeBuilder::MoreVertices() const
{
return (current < 3);
}
//=================================================================================================
void HLRBRep_EdgeBuilder::NextVertex()
{
if (current == 1)
{
current = 2;
if (right.IsNull())
{
current = 3;
}
}
else if (current == 2)
{
NextArea();
if ((AreaState() == toBuild) && (AreaEdgeState() == TopAbs_IN))
{
current = 2;
}
else
{
current = 3;
}
}
else
{
throw Standard_NoSuchObject("EdgeBuilder::NextVertex : No current edge");
}
}
//=================================================================================================
const HLRAlgo_Intersection& HLRBRep_EdgeBuilder::Current() const
{
if (current == 1)
{
return left->Vertex();
}
else if (current == 2)
{
return right->Vertex();
}
else
{
throw Standard_NoSuchObject("EdgeBuilder::Current : No current vertex");
}
}
//=================================================================================================
bool HLRBRep_EdgeBuilder::IsBoundary() const
{
if (current == 1)
{
return left->IsBoundary();
}
else if (current == 2)
{
return right->IsBoundary();
}
else
{
throw Standard_NoSuchObject("EdgeBuilder::IsBoundary : No current vertex");
}
}
//=================================================================================================
bool HLRBRep_EdgeBuilder::IsInterference() const
{
if (current == 1)
{
return left->IsInterference();
}
else if (current == 2)
{
return right->IsInterference();
}
else
{
throw Standard_NoSuchObject("EdgeBuilder::IsInterference : No current vertex");
}
}
//=================================================================================================
TopAbs_Orientation HLRBRep_EdgeBuilder::Orientation() const
{
if (current == 1)
{
if ((left->StateBefore() == left->StateAfter()) && (left->EdgeBefore() == left->EdgeAfter()))
{
return TopAbs_INTERNAL;
}
else
{
return TopAbs_FORWARD;
}
}
else if (current == 2)
{
if ((right->StateBefore() == right->StateAfter())
&& (right->EdgeBefore() == right->EdgeAfter()))
{
return TopAbs_INTERNAL;
}
else
{
return TopAbs_REVERSED;
}
}
return TopAbs_EXTERNAL; // only for WNT.
}
//=================================================================================================
void HLRBRep_EdgeBuilder::Destroy()
{
occ::handle<HLRBRep_AreaLimit> cur = myLimits;
while (!cur.IsNull())
{
occ::handle<HLRBRep_AreaLimit> n = cur->Next();
cur->Clear();
cur = n;
}
left.Nullify();
right.Nullify();
myLimits.Nullify();
}