613 lines
15 KiB
C++
613 lines
15 KiB
C++
/*! \file ../src/node.cpp
|
|
\brief Holds a GDSII node structure
|
|
\author Probably Klaas Holwerda
|
|
|
|
Copyright: 2001-2004 (C) Probably Klaas Holwerda
|
|
|
|
Licence: wxWidgets Licence
|
|
|
|
RCS-ID: $Id: node.cpp,v 1.7 2005/06/17 23:01:03 kbluck Exp $
|
|
*/
|
|
#ifdef __GNUG__
|
|
#pragma implementation
|
|
#endif
|
|
|
|
#include "../include/node.h"
|
|
#include "../include/link.h"
|
|
#include "../include/line.h"
|
|
#include <math.h>
|
|
|
|
//this here is to initialize the static iterator of node
|
|
//with NOLIST constructor
|
|
//TDLI<KBoolLink> Node::_linkiter=TDLI<KBoolLink>(_GC);
|
|
|
|
Node::Node(Bool_Engine* GC) : LPoint(0,0)
|
|
{
|
|
_GC=GC;
|
|
_linklist=new DL_List<void*>();
|
|
}
|
|
|
|
|
|
Node::Node(B_INT const X, B_INT const Y, Bool_Engine* GC) : LPoint(X,Y)
|
|
{
|
|
_GC=GC;
|
|
_linklist=new DL_List<void*>();
|
|
}
|
|
|
|
|
|
Node::Node(LPoint* const a_point, Bool_Engine* GC) : LPoint(a_point)
|
|
{
|
|
_GC=GC;
|
|
_linklist=new DL_List<void*>();
|
|
}
|
|
|
|
|
|
//Node::Node(Node * const other) : LPoint(other)
|
|
Node::Node(Node * const other, Bool_Engine* GC)
|
|
{
|
|
_GC=GC;
|
|
_x = other->_x;
|
|
_y = other->_y;
|
|
_linklist=new DL_List<void*>();
|
|
}
|
|
|
|
Node& Node::operator=(const Node &other_node)
|
|
{
|
|
_x = other_node._x;
|
|
_y = other_node._y;
|
|
|
|
return *this;
|
|
}
|
|
|
|
|
|
// x and y of the point will be rounded to the nearest
|
|
// xnew=N*grid and ynew=N*grid
|
|
void Node::RoundInt(B_INT grid)
|
|
{
|
|
_x=(B_INT) floor((_x + grid * 0.5) / grid) * grid;
|
|
_y=(B_INT) floor((_y + grid * 0.5) / grid) * grid;
|
|
}
|
|
|
|
Node::~Node()
|
|
{
|
|
delete _linklist;
|
|
}
|
|
|
|
DL_List<void*>* Node::GetLinklist()
|
|
{
|
|
return _linklist;
|
|
}
|
|
|
|
void Node::AddLink(KBoolLink *a_link)
|
|
{
|
|
// assert(a_link);
|
|
_linklist->insbegin(a_link);
|
|
}
|
|
|
|
KBoolLink* Node::GetIncomingLink()
|
|
{
|
|
if (((KBoolLink*)_linklist->headitem())->GetEndNode() == this)
|
|
return (KBoolLink*)_linklist->headitem();
|
|
else
|
|
return (KBoolLink*)_linklist->tailitem();
|
|
}
|
|
|
|
KBoolLink* Node::GetOutgoingLink()
|
|
{
|
|
if (((KBoolLink*)_linklist->headitem())->GetBeginNode() == this)
|
|
return (KBoolLink*)_linklist->headitem();
|
|
else
|
|
return (KBoolLink*)_linklist->tailitem();
|
|
}
|
|
|
|
//
|
|
// Returns the number of connected links
|
|
//
|
|
int Node::GetNumberOfLinks()
|
|
{
|
|
return _linklist->count();
|
|
}
|
|
|
|
KBoolLink* Node::GetOtherLink(KBoolLink* prev)
|
|
{
|
|
if (prev==(KBoolLink*)_linklist->headitem())
|
|
return (KBoolLink*)_linklist->tailitem();
|
|
if (prev==(KBoolLink*)_linklist->tailitem())
|
|
return (KBoolLink*)_linklist->headitem();
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
int Node::Merge(Node *other)
|
|
{
|
|
if (this==other) //they are already merged dummy
|
|
return 0;
|
|
|
|
_GC->_linkiter->Attach(_linklist);
|
|
int Counter;
|
|
// used to delete Iterator on other->_linklist
|
|
// otherwise there can't be a takeover, because for takeover there can't
|
|
// be an iterator on other->_linklist;
|
|
{
|
|
TDLI<KBoolLink> Iother(other->_linklist);
|
|
KBoolLink* temp;
|
|
|
|
Counter = Iother.count();
|
|
|
|
Iother.tohead();
|
|
while (!Iother.hitroot())
|
|
{
|
|
temp=Iother.item();
|
|
//need to test both nodes because it may be a zero length link
|
|
if (temp->GetEndNode()==other)
|
|
temp->SetEndNode(this);
|
|
if (temp->GetBeginNode()==other)
|
|
temp->SetBeginNode(this);
|
|
Iother++;
|
|
}
|
|
_GC->_linkiter->takeover(&Iother);
|
|
}
|
|
_GC->_linkiter->Detach();
|
|
|
|
//at this moment the other nodes has no link pointing to it so it needs to be deleted
|
|
delete other;
|
|
return Counter;
|
|
}
|
|
|
|
|
|
void Node::RemoveLink(KBoolLink *a_link)
|
|
{
|
|
// assert(a_link);
|
|
_GC->_linkiter->Attach(_linklist);
|
|
|
|
if (_GC->_linkiter->toitem(a_link)) // find the link
|
|
_GC->_linkiter->remove();
|
|
_GC->_linkiter->Detach();
|
|
}
|
|
|
|
// This function will determinate if the given three points
|
|
// can be simplified to two points
|
|
//
|
|
// input : three nodes, the first and the second must be points of
|
|
// a line in correct order, the third point is a point of another
|
|
// line.
|
|
// output: -
|
|
// return: true if points can be simplified
|
|
// false if points can't be simplified
|
|
bool Node::Simplify(Node *First, Node *Second, B_INT Marge)
|
|
{
|
|
double distance=0;
|
|
|
|
// The first and second point are a zero line, if so we can
|
|
// make a line between the first and third point
|
|
if (First->Equal(Second,Marge))
|
|
return true;
|
|
|
|
// Are the first and third point equal, if so
|
|
// we can delete the second point
|
|
if (First->Equal(this, Marge))
|
|
return true;
|
|
|
|
// Used tmp_link.set here, because the link may not be linked in the graph,
|
|
// because the point of the graphs are used, after use of the line we have
|
|
//to set the link to zero so the nodes will not be destructed by exit of the function
|
|
KBoolLink tmp_link(_GC);
|
|
tmp_link.Set(First,Second);
|
|
KBoolLine tmp_line(_GC);
|
|
tmp_line.Set(&tmp_link);
|
|
|
|
// If third point is on the same line which is made from the first
|
|
// and second point then we can delete the second point
|
|
if (tmp_line.PointOnLine(this,distance, (double) Marge) == ON_AREA)
|
|
{
|
|
tmp_link.Set(NULL,NULL);
|
|
return true;
|
|
}
|
|
//
|
|
//
|
|
tmp_link.Set(Second,this);
|
|
tmp_line.Set(&tmp_link);
|
|
if (tmp_line.PointOnLine(First,distance, (double) Marge) == ON_AREA)
|
|
{
|
|
tmp_link.Set(NULL,NULL);
|
|
return true;
|
|
}
|
|
tmp_link.Set(NULL,NULL);
|
|
return false;
|
|
}
|
|
|
|
|
|
KBoolLink* Node::GetNextLink()
|
|
{
|
|
int Aantal = _linklist->count();
|
|
|
|
// assert (Aantal != 0);
|
|
|
|
// there is one link, so there is no previous link
|
|
if (Aantal == 1)
|
|
return NULL;
|
|
int Marked_Counter = 0;
|
|
KBoolLink *the_link = NULL;
|
|
|
|
// count the marked links
|
|
_GC->_linkiter->Attach(_linklist);
|
|
_GC->_linkiter->tohead();
|
|
while (!_GC->_linkiter->hitroot())
|
|
{
|
|
if (_GC->_linkiter->item()->IsMarked())
|
|
Marked_Counter++;
|
|
else
|
|
{
|
|
if (!the_link)
|
|
the_link = _GC->_linkiter->item();
|
|
}
|
|
(*_GC->_linkiter)++;
|
|
}
|
|
_GC->_linkiter->Detach();
|
|
if (Aantal - Marked_Counter != 1)
|
|
// there arent two unmarked links
|
|
return NULL;
|
|
else
|
|
{
|
|
if (the_link->GetBeginNode() == this)
|
|
return the_link;
|
|
else
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
|
|
KBoolLink* Node::GetPrevLink()
|
|
{
|
|
int Aantal;
|
|
if (!_linklist)
|
|
return NULL;
|
|
|
|
Aantal = _linklist->count();
|
|
|
|
// assert (Aantal != 0);
|
|
|
|
// there is one link, so there is no previous link
|
|
if (Aantal == 1)
|
|
return NULL;
|
|
|
|
int Marked_Counter = 0;
|
|
KBoolLink *the_link = NULL;
|
|
|
|
_GC->_linkiter->Attach(_linklist);
|
|
// count the marked links
|
|
_GC->_linkiter->tohead();
|
|
while (!_GC->_linkiter->hitroot())
|
|
{
|
|
if (_GC->_linkiter->item()->IsMarked())
|
|
Marked_Counter++;
|
|
else
|
|
{
|
|
if (!the_link)
|
|
the_link = _GC->_linkiter->item();
|
|
}
|
|
(*_GC->_linkiter)++;
|
|
}
|
|
_GC->_linkiter->Detach();
|
|
if (Aantal - Marked_Counter != 1)
|
|
// there arent two unmarked links
|
|
return NULL;
|
|
else
|
|
{
|
|
if (the_link->GetEndNode() == this)
|
|
return the_link;
|
|
else
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
bool Node::SameSides( KBoolLink* const prev , KBoolLink* const link, BOOL_OP operation )
|
|
{
|
|
bool directedLeft;
|
|
bool directedRight;
|
|
if ( prev->GetEndNode() == this ) //forward direction
|
|
{
|
|
directedLeft = prev->IsMarkedLeft( operation );
|
|
directedRight = prev->IsMarkedRight( operation );
|
|
if ( link->GetBeginNode() == this ) //forward direction
|
|
{
|
|
return directedLeft == link->IsMarkedLeft( operation ) &&
|
|
directedRight == link->IsMarkedRight( operation );
|
|
}
|
|
|
|
return directedLeft == link->IsMarkedRight( operation ) &&
|
|
directedRight == link->IsMarkedLeft( operation );
|
|
}
|
|
|
|
directedLeft = prev->IsMarkedRight( operation );
|
|
directedRight = prev->IsMarkedLeft( operation );
|
|
if ( link->GetBeginNode() == this ) //forward direction
|
|
{
|
|
return directedLeft == link->IsMarkedLeft( operation ) &&
|
|
directedRight == link->IsMarkedRight( operation );
|
|
}
|
|
return directedLeft == link->IsMarkedRight( operation ) &&
|
|
directedRight == link->IsMarkedLeft( operation );
|
|
}
|
|
|
|
// on the node get the link
|
|
// is the most right or left one
|
|
// This function is used to collect the simple graphs from a graph
|
|
KBoolLink* Node::GetMost( KBoolLink* const prev ,LinkStatus whatside, BOOL_OP operation )
|
|
{
|
|
KBoolLink *reserve=0;
|
|
KBoolLink *Result = NULL,*link;
|
|
Node* prevbegin = prev->GetOther(this);
|
|
|
|
if (_linklist->count() == 2) // only two links to this node take the one != prev
|
|
{
|
|
if ( (link = (KBoolLink*)_linklist->headitem()) == prev ) //this is NOT the one to go on
|
|
link = (KBoolLink*)_linklist->tailitem();
|
|
if (!link->BeenHere() && SameSides( prev, link, operation ) )
|
|
//we are back where we started (bin is true) return Null
|
|
return link;
|
|
return(0);
|
|
}
|
|
|
|
_GC->_linkiter->Attach(_linklist);
|
|
_GC->_linkiter->tohead();
|
|
//more then 2 links to the Node
|
|
while(!_GC->_linkiter->hitroot())
|
|
{
|
|
link = _GC->_linkiter->item();
|
|
if ( !link->BeenHere() &&
|
|
SameSides( prev, link, operation ) &&
|
|
link != prev //should be set to bin already
|
|
)
|
|
{
|
|
if (prevbegin == link->GetOther(this) )//pointers equal
|
|
//we are going back in the same direction on a parallel link
|
|
//only take this possibility if nothing else is possible
|
|
reserve = link;
|
|
else
|
|
{ //this link is in a different direction
|
|
if (!Result)
|
|
Result = link; //first one found sofar
|
|
else
|
|
{
|
|
if (prev->PointOnCorner(Result, link) == whatside )
|
|
//more to the whatside than take this one
|
|
Result = link;
|
|
}
|
|
}
|
|
}
|
|
(*_GC->_linkiter)++;
|
|
}
|
|
|
|
// if there is a next link found return it
|
|
// else if a parallel link is found return that one
|
|
// else return NULL
|
|
_GC->_linkiter->Detach();
|
|
return ((Result) ? Result : reserve);
|
|
}
|
|
|
|
// on the node get the link
|
|
// is the most right or left one
|
|
// This function is used to collect the simple graphs from a graph
|
|
KBoolLink* Node::GetMostHole( KBoolLink* const prev, LinkStatus whatside, BOOL_OP operation )
|
|
{
|
|
KBoolLink *reserve=0;
|
|
KBoolLink *Result=NULL,*link;
|
|
Node* prevbegin = prev->GetOther(this);
|
|
|
|
if (_linklist->count() == 2) // only two links to this node take the one != prev
|
|
{
|
|
if ( (link = (KBoolLink*)_linklist->headitem()) == prev ) //this is NOT the one to go on
|
|
link = (KBoolLink*)_linklist->tailitem();
|
|
if ( link->GetHole() && !link->GetHoleLink() && !link->BeenHere() && SameSides( prev, link, operation ) )
|
|
//we are back where we started (bin is true) return Null
|
|
return link;
|
|
return(0);
|
|
}
|
|
|
|
_GC->_linkiter->Attach(_linklist);
|
|
_GC->_linkiter->tohead();
|
|
//more then 2 links to the Node
|
|
while(!_GC->_linkiter->hitroot())
|
|
{
|
|
link = _GC->_linkiter->item();
|
|
if ( !link->BeenHere() &&
|
|
link->GetHole() &&
|
|
!link->GetHoleLink() &&
|
|
SameSides( prev, link, operation ) &&
|
|
link != prev //should be set to bin already
|
|
)
|
|
{
|
|
if (prevbegin == link->GetOther(this) )//pointers equal
|
|
//we are going back in the same direction on a parallel link
|
|
//only take this possibility if nothing else is possible
|
|
reserve = link;
|
|
else
|
|
{ //this link is in a different direction
|
|
if (!Result)
|
|
Result = link; //first one found sofar
|
|
else
|
|
{
|
|
if (prev->PointOnCorner(Result, link) == whatside )
|
|
//more to the whatside than take this one
|
|
Result = link;
|
|
}
|
|
}
|
|
}
|
|
(*_GC->_linkiter)++;
|
|
}
|
|
|
|
// if there is a next link found return it
|
|
// else if a parallel link is found return that one
|
|
// else return NULL
|
|
_GC->_linkiter->Detach();
|
|
return ((Result) ? Result : reserve);
|
|
}
|
|
|
|
// this function gets the highest not flat link
|
|
KBoolLink* Node::GetHoleLink( KBoolLink* const prev, bool checkbin, BOOL_OP operation )
|
|
{
|
|
KBoolLink *Result=NULL,*link;
|
|
|
|
_GC->_linkiter->Attach(_linklist);
|
|
|
|
for(_GC->_linkiter->tohead();!_GC->_linkiter->hitroot();(*_GC->_linkiter)++)
|
|
{
|
|
link=_GC->_linkiter->item();
|
|
if ( link->GetHoleLink() &&
|
|
( !checkbin || ( checkbin && !link->BeenHere()) ) &&
|
|
SameSides( prev, link, operation )
|
|
)
|
|
{
|
|
Result=link;
|
|
break;
|
|
}
|
|
}
|
|
|
|
_GC->_linkiter->Detach();
|
|
return (Result);
|
|
}
|
|
|
|
// this function gets the highest not flat link
|
|
KBoolLink* Node::GetNotFlat()
|
|
{
|
|
KBoolLink *Result=NULL,*link;
|
|
|
|
_GC->_linkiter->Attach(_linklist);
|
|
|
|
double tangold = 0.0;
|
|
double tangnew = 0.0;
|
|
|
|
for(_GC->_linkiter->tohead();!_GC->_linkiter->hitroot();(*_GC->_linkiter)++)
|
|
{
|
|
link=_GC->_linkiter->item();
|
|
if (!_GC->_linkiter->item()->BeenHere())
|
|
{
|
|
B_INT dx=link->GetOther(this)->GetX()-_x;
|
|
B_INT dy=link->GetOther(this)->GetY()-_y;
|
|
if (dx!=0)
|
|
{
|
|
tangnew=fabs( (double) dy / (double) dx );
|
|
}
|
|
else
|
|
{
|
|
tangnew=MAXDOUBLE;
|
|
}
|
|
|
|
if (!Result)
|
|
{
|
|
//this link is in a different direction
|
|
Result=link; //first one found sofar
|
|
tangold=tangnew;
|
|
}
|
|
else
|
|
{
|
|
if(tangnew < tangold)
|
|
{
|
|
//this one is higher (more horizontal) then the old Result
|
|
Result=link;
|
|
tangold=tangnew;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// if there is a next link found return it
|
|
// else if a parallel link is found return that one
|
|
// else return NULL
|
|
_GC->_linkiter->Detach();
|
|
return (Result);
|
|
}
|
|
|
|
// on the node get the link that is not BIN
|
|
// and that has the same graphnumber and is in same direction
|
|
KBoolLink *Node::Follow(KBoolLink* const prev )
|
|
{
|
|
KBoolLink *temp;
|
|
_GC->_linkiter->Attach(_linklist);
|
|
|
|
_GC->_linkiter->tohead();
|
|
while(!_GC->_linkiter->hitroot())
|
|
{
|
|
if (( _GC->_linkiter->item() != prev ) &&
|
|
( !_GC->_linkiter->item()->BeenHere()) &&
|
|
( _GC->_linkiter->item()->GetGraphNum() == prev->GetGraphNum()) &&
|
|
(
|
|
( (prev->GetEndNode() == this) &&
|
|
(_GC->_linkiter->item()->GetEndNode() !=this)
|
|
)
|
|
||
|
|
( (prev->GetBeginNode() == this) &&
|
|
(_GC->_linkiter->item()->GetBeginNode() !=this)
|
|
)
|
|
)
|
|
)
|
|
{
|
|
temp=_GC->_linkiter->item();
|
|
_GC->_linkiter->Detach();
|
|
return(temp);
|
|
}
|
|
(*_GC->_linkiter)++;
|
|
}
|
|
|
|
_GC->_linkiter->Detach();
|
|
return (0);
|
|
}
|
|
|
|
// this function gets the highest (other node) link ascending from the node
|
|
// that has the bin flag set as the argument binset
|
|
// if no such link exists return 0
|
|
KBoolLink* Node::GetBinHighest(bool binset)
|
|
{
|
|
KBoolLink *Result=NULL,*link;
|
|
_GC->_linkiter->Attach(_linklist);
|
|
|
|
double tangold = 0.0;
|
|
double tangnew = 0.0;
|
|
|
|
for(_GC->_linkiter->tohead();!_GC->_linkiter->hitroot();(*_GC->_linkiter)++)
|
|
{
|
|
link=_GC->_linkiter->item();
|
|
if (_GC->_linkiter->item()->BeenHere() == binset)
|
|
{
|
|
B_INT dx=link->GetOther(this)->GetX()-_x;
|
|
B_INT dy=link->GetOther(this)->GetY()-_y;
|
|
if (dx!=0)
|
|
{
|
|
tangnew = (double) dy / (double) dx;
|
|
}
|
|
else if (dy > 0)
|
|
{
|
|
tangnew = MAXDOUBLE;
|
|
}
|
|
else
|
|
{
|
|
tangnew = -MAXDOUBLE;
|
|
}
|
|
|
|
if (!Result)
|
|
{
|
|
Result = link; //first one found sofar
|
|
tangold = tangnew;
|
|
}
|
|
else
|
|
{
|
|
if(tangnew > tangold)
|
|
{
|
|
//this one is higher then the old Result
|
|
Result = link;
|
|
tangold = tangnew;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// if there is a link found return it
|
|
// else return NULL
|
|
_GC->_linkiter->Detach();
|
|
return (Result);
|
|
}
|
|
|
|
|