kicad/polygon/kbool/src/record.cpp

353 lines
9.5 KiB
C++

/*! \file src/record.cpp
\author Klaas Holwerda or Julian Smart
Copyright: 2001-2004 (C) Klaas Holwerda
Licence: see kboollicense.txt
RCS-ID: $Id: record.cpp,v 1.3 2008/06/04 21:23:22 titato Exp $
*/
#include "kbool/booleng.h"
#include "kbool/record.h"
#include "kbool/node.h"
#include <stdlib.h>
#include <math.h>
#define LNK _line.GetLink()
//int r_index=-1;
//void* _Record_Pool[30];
//void DeleteRecordPool()
//{
// while (r_index!=-1)
// {
// free( _Record_Pool[r_index--]);
// }
//}
Record::~Record()
{}
//void* Record::operator new(size_t size)
//{
//
// if (r_index!=-1)
// {
// return _Record_Pool[r_index--];
// }
//
// return malloc(size);
//}
//void Record::operator delete(void* recordptr)
//{
//
// if (r_index < 28)
// {
// _Record_Pool[++r_index]= recordptr;
// return;
// }
//
// free (recordptr);
//}
//void Record::deletepool()
//{
//
// while (r_index!=-1)
// {
// free( _Record_Pool[r_index--]);
// }
//}
Record::Record( KBoolLink* link, Bool_Engine* GC )
: _line( GC )
{
_GC = GC;
_dir = GO_RIGHT;
_a = 0;
_b = 0;
_line.Set( link );
_line.CalculateLineParameters();
}
//when the dimensions of a link for a record changes, its line parameters need to be recalculated
void Record::SetNewLink( KBoolLink* link )
{
_line.Set( link );
_line.CalculateLineParameters();
}
//for beams calculate the ysp on the low scanline
void Record::Calc_Ysp( Node* low )
{
if ( ( LNK->GetEndNode() == low ) || ( LNK->GetBeginNode() == low ) )
{
_ysp = low->GetY();
return;
}
if ( LNK->GetEndNode()->GetX() == LNK->GetBeginNode()->GetX() )
_ysp = low->GetY(); //flatlink only in flatbeams
else if ( LNK->GetEndNode()->GetX() == low->GetX() )
_ysp = LNK->GetEndNode()->GetY();
else if ( LNK->GetBeginNode()->GetX() == low->GetX() )
_ysp = LNK->GetBeginNode()->GetY();
else
_ysp = _line.Calculate_Y_from_X( low->GetX() );
}
//to set the _dir for new links in the beam
void Record::Set_Flags()
{
if ( LNK->GetEndNode()->GetX() == LNK->GetBeginNode()->GetX() ) //flatlink ?
{ //only happens in flat beams
if ( LNK->GetEndNode()->GetY() < LNK->GetBeginNode()->GetY() )
_dir = GO_RIGHT;
else
_dir = GO_LEFT;
}
else
{
if ( LNK->GetEndNode()->GetX() > LNK->GetBeginNode()->GetX() )
_dir = GO_RIGHT;
else
_dir = GO_LEFT;
}
}
KBoolLink* Record::GetLink()
{
return LNK;
}
B_INT Record::Ysp()
{
return _ysp;
}
void Record::SetYsp( B_INT ysp )
{
_ysp = ysp;
}
DIRECTION Record::Direction()
{
return DIRECTION( _dir );
}
bool Record::Calc_Left_Right( Record* record_above_me )
{
bool par = false;
if ( !record_above_me ) //null if no record above
{ _a = 0;_b = 0; }
else
{
_a = record_above_me->_a;
_b = record_above_me->_b;
}
switch ( _dir & 1 )
{
case GO_LEFT : if ( LNK->Group() == GROUP_A )
{
LNK->SetRightA( ( bool )( _a > 0 ) );
if ( _GC->GetWindingRule() )
LNK->GetInc() ? _a++ : _a--;
else
{ //ALTERNATE
if ( _a )
_a = 0;
else
_a = 1;
}
LNK->SetLeftA( ( bool )( _a > 0 ) );
LNK->SetLeftB( ( bool )( _b > 0 ) );
LNK->SetRightB( ( bool )( _b > 0 ) );
}
else
{
LNK->SetRightA( ( bool )( _a > 0 ) );
LNK->SetLeftA( ( bool )( _a > 0 ) );
LNK->SetRightB( ( bool )( _b > 0 ) );
if ( _GC->GetWindingRule() )
LNK->GetInc() ? _b++ : _b--;
else //ALTERNATE
{
if ( _b )
_b = 0;
else
_b = 1;
}
LNK->SetLeftB( ( bool )( _b > 0 ) );
}
break;
case GO_RIGHT : if ( LNK->Group() == GROUP_A )
{
LNK->SetLeftA( ( bool )( _a > 0 ) );
if ( _GC->GetWindingRule() )
LNK->GetInc() ? _a++ : _a--;
else
{ //ALTERNATE
if ( _a )
_a = 0;
else
_a = 1;
}
LNK->SetRightA( ( bool )( _a > 0 ) );
LNK->SetLeftB( ( bool )( _b > 0 ) );
LNK->SetRightB( ( bool )( _b > 0 ) );
}
else
{
LNK->SetRightA( ( bool )( _a > 0 ) );
LNK->SetLeftA( ( bool )( _a > 0 ) );
LNK->SetLeftB( ( bool )( _b > 0 ) );
if ( _GC->GetWindingRule() )
LNK->GetInc() ? _b++ : _b--;
else
{ //ALTERNATE
if ( _b )
_b = 0;
else
_b = 1;
}
LNK->SetRightB( ( bool )( _b > 0 ) );
}
break;
default : _GC->error( "Undefined Direction of link", "function IScanBeam::Calc_Set_Left_Right()" );
break;
}
//THE NEXT WILL WORK for MOST windingrule polygons,
//even when not taking into acount windingrule
// not all
/*
switch (_dir&1)
{
case GO_LEFT : if (LNK->Group() == GROUP_A)
{
LNK->SetRightA((bool)(_a>0));
if (booleng->Get_WindingRule())
LNK->GetInc() ? _a++ : _a--;
else
_a--;
LNK->SetLeftA((bool)(_a>0));
LNK->SetLeftB((bool)(_b>0));
LNK->SetRightB((bool)(_b>0));
}
else
{
LNK->SetRightA((bool)(_a > 0));
LNK->SetLeftA((bool)(_a>0));
LNK->SetRightB((bool)(_b>0));
if (booleng->Get_WindingRule())
LNK->GetInc() ? _b++ : _b--;
else
_b--;
LNK->SetLeftB((bool)(_b>0));
}
break;
case GO_RIGHT : if (LNK->Group() == GROUP_A)
{
LNK->SetLeftA((bool)(_a>0));
if (booleng->Get_WindingRule())
LNK->GetInc() ? _a++ : _a--;
else
_a++;
LNK->SetRightA((bool)(_a>0));
LNK->SetLeftB((bool)(_b>0));
LNK->SetRightB((bool)(_b>0));
}
else
{
LNK->SetRightA((bool)(_a>0));
LNK->SetLeftA((bool)(_a>0));
LNK->SetLeftB((bool)(_b>0));
if (booleng->Get_WindingRule())
LNK->GetInc() ? _b++ : _b--;
else
_b++;
LNK->SetRightB((bool)(_b>0));
}
break;
default : _messagehandler->error("Undefined Direction of link","function IScanBeam::Calc_Set_Left_Right()");
break;
}
*/
//if the records are parallel (same begin/endnodes)
//the above link a/b flag are adjusted to the current a/b depth
if ( record_above_me && Equal( record_above_me ) )
{
par = true;
LNK->Mark();
record_above_me->_a = _a;
record_above_me->_b = _b;
if ( Direction() == GO_LEFT )
{
//set the bottom side of the above link
if ( record_above_me->Direction() == GO_LEFT )
{
record_above_me->LNK->SetLeftA( LNK->GetLeftA() );
record_above_me->LNK->SetLeftB( LNK->GetLeftB() );
}
else
{
record_above_me->LNK->SetRightA( LNK->GetLeftA() );
record_above_me->LNK->SetRightB( LNK->GetLeftB() );
}
}
else
{
//set the bottom side of the above link
if ( record_above_me->Direction() == GO_LEFT )
{
record_above_me->LNK->SetLeftA( LNK->GetRightA() );
record_above_me->LNK->SetLeftB( LNK->GetRightB() );
}
else
{
record_above_me->LNK->SetRightA( LNK->GetRightA() );
record_above_me->LNK->SetRightB( LNK->GetRightB() );
}
}
}
return par;
}
bool Record::Equal( Record *a )
{
return( ( bool )( ( LNK->GetOther( a->LNK->GetBeginNode() ) == a->LNK->GetEndNode() ) &&
( LNK->GetOther( a->LNK->GetEndNode() ) == a->LNK->GetBeginNode() ) ) );
}
KBoolLine* Record::GetLine()
{
return & _line;
}