- Changed FEventTree into a regular binary tree, since there just aren't enough

nodes inserted into it to make a red-black tree worthwhile.
- Added more checks at the start of ClassifyLine so that it has a better chance
  of avoiding the more complicated checking, and it seems to have paid off with
  a reasonably modest performance boost.

SVN r169 (trunk)
This commit is contained in:
Randy Heit 2006-06-06 05:00:46 +00:00
parent 738eabc6be
commit cf0d73b128
5 changed files with 28 additions and 236 deletions

View file

@ -507,12 +507,14 @@ static bool CheckInOutNames ()
angle_t PointToAngle (fixed_t x, fixed_t y)
{
const double rad2bam = double(1<<30) / M_PI;
double ang = atan2 (double(y), double(x));
const double rad2bam = double(1<<30) / M_PI;
#if 0
if (ang < 0.0)
{
ang = 2*M_PI+ang;
}
#endif
return angle_t(ang * rad2bam) << 1;
}

View file

@ -713,8 +713,13 @@ int FNodeBuilder::Heuristic (node_t &node, DWORD set, bool honorNoSplit)
return score;
}
// Returns:
// 0 = seg is in front
// 1 = seg is in back
// -1 = seg cuts the node
int FNodeBuilder::ClassifyLine (node_t &node, const FPrivSeg *seg, int &sidev1, int &sidev2)
{
#define FAR_ENOUGH 17179869184.f // 4<<32
const FPrivVert *v1 = &Vertices[seg->v1];
const FPrivVert *v2 = &Vertices[seg->v2];
@ -727,21 +732,33 @@ int FNodeBuilder::ClassifyLine (node_t &node, const FPrivSeg *seg, int &sidev1,
double d_yv1 = double(v1->y);
double d_yv2 = double(v2->y);
double s_num1 = (d_y1 - d_yv1)*d_dx - (d_x1 - d_xv1) * d_dy;
double s_num2 = (d_y1 - d_yv2)*d_dx - (d_x1 - d_xv2) * d_dy;
double s_num1 = (d_y1 - d_yv1) * d_dx - (d_x1 - d_xv1) * d_dy;
double s_num2 = (d_y1 - d_yv2) * d_dx - (d_x1 - d_xv2) * d_dy;
if (s_num1 <= -17179869184.0 && s_num2 <= -17179869184.0)
if (s_num1 <= -FAR_ENOUGH && s_num2 <= -FAR_ENOUGH)
{
sidev1 = sidev2 = 1;
return 1;
}
if (s_num1 >= 17179869184.0 && s_num2 >= 17179869184.0)
if (s_num1 >= FAR_ENOUGH && s_num2 >= FAR_ENOUGH)
{
sidev1 = sidev2 = -1;
return 0;
}
if (s_num1 <= -FAR_ENOUGH && s_num2 >= FAR_ENOUGH)
{
sidev1 = 1;
sidev2 = -1;
return -1;
}
if (s_num1 >= FAR_ENOUGH && s_num2 <= -FAR_ENOUGH)
{
sidev1 = -1;
sidev2 = 1;
return -1;
}
int near = (fabs(s_num1) < 17179869184.0) | ((fabs(s_num2) < 17179869184.0) << 1);
int near = (fabs(s_num1) < FAR_ENOUGH) | ((fabs(s_num2) < FAR_ENOUGH) << 1);
if (near)
{
double l = 1.0 / (d_dx*d_dx + d_dy*d_dy);
@ -1133,7 +1150,7 @@ int FNodeBuilder::PointOnSide (int x, int y, int x1, int y1, int dx, int dy)
double s_num = (d_y1-d_y)*d_dx - (d_x1-d_x)*d_dy;
if (fabs(s_num) < 17179869184.0) // 4<<32
if (fabs(s_num) < 17179869184.f) // 4<<32
{
// Either the point is very near the line, or the segment defining
// the line is very short: Do a more expensive test to determine

View file

@ -11,7 +11,6 @@ struct FEventInfo
struct FEvent
{
FEvent *Parent, *Left, *Right;
enum { RED, BLACK } Color;
double Distance;
FEventInfo Info;
};
@ -28,7 +27,6 @@ public:
FEvent *GetNewNode ();
void Insert (FEvent *event);
void Delete (FEvent *event);
FEvent *FindEvent (double distance) const;
void DeleteAll ();
@ -39,9 +37,6 @@ private:
FEvent *Root;
FEvent *Spare;
void LeftRotate (FEvent *event);
void RightRotate (FEvent *event);
void DeleteFixUp (FEvent *event);
void DeletionTraverser (FEvent *event);
FEvent *Successor (FEvent *event) const;
FEvent *Predecessor (FEvent *event) const;

View file

@ -27,7 +27,6 @@ FEventTree::FEventTree ()
: Root (&Nil), Spare (NULL)
{
memset (&Nil, 0, sizeof(Nil));
Nil.Color = FEvent::BLACK;
}
FEventTree::~FEventTree ()
@ -61,56 +60,6 @@ void FEventTree::DeletionTraverser (FEvent *node)
}
}
void FEventTree::LeftRotate (FEvent *x)
{
FEvent *y = x->Right;
x->Right = y->Left;
if (y->Left != &Nil)
{
y->Left->Parent = x;
}
y->Parent = x->Parent;
if (x->Parent == &Nil)
{
Root = y;
}
else if (x == x->Parent->Left)
{
x->Parent->Left = y;
}
else
{
x->Parent->Right = y;
}
y->Left = x;
x->Parent = y;
}
void FEventTree::RightRotate (FEvent *x)
{
FEvent *y = x->Left;
x->Left = y->Right;
if (y->Right != &Nil)
{
y->Right->Parent = x;
}
y->Parent = x->Parent;
if (x->Parent == &Nil)
{
Root = y;
}
else if (x == x->Parent->Left)
{
x->Parent->Left = y;
}
else
{
x->Parent->Right = y;
}
y->Right = x;
x->Parent = y;
}
FEvent *FEventTree::GetNewNode ()
{
FEvent *node;
@ -159,176 +108,6 @@ void FEventTree::Insert (FEvent *z)
}
z->Left = &Nil;
z->Right = &Nil;
// printf ("Inserted distance %g, vertex %d, seg %d\n",
// sqrt(z->Distance/4294967296.0), z->Info.Vertex, z->Info.FrontSeg);
z->Color = FEvent::RED;
while (z != Root && z->Parent->Color == FEvent::RED)
{
if (z->Parent == z->Parent->Parent->Left)
{
y = z->Parent->Parent->Right;
if (y->Color == FEvent::RED)
{
z->Parent->Color = FEvent::BLACK;
y->Color = FEvent::BLACK;
z->Parent->Parent->Color = FEvent::RED;
z = z->Parent->Parent;
}
else
{
if (z == z->Parent->Right)
{
z = z->Parent;
LeftRotate (z);
}
z->Parent->Color = FEvent::BLACK;
z->Parent->Parent->Color = FEvent::RED;
RightRotate (z->Parent->Parent);
}
}
else
{
y = z->Parent->Parent->Left;
if (y->Color == FEvent::RED)
{
z->Parent->Color = FEvent::BLACK;
y->Color = FEvent::BLACK;
z->Parent->Parent->Color = FEvent::RED;
z = z->Parent->Parent;
}
else
{
if (z == z->Parent->Left)
{
z = z->Parent;
RightRotate (z);
}
z->Parent->Color = FEvent::BLACK;
z->Parent->Parent->Color = FEvent::RED;
LeftRotate (z->Parent->Parent);
}
}
}
Root->Color = FEvent::BLACK;
}
void FEventTree::Delete (FEvent *z)
{
FEvent *x, *y;
if (z->Left == &Nil || z->Right == &Nil)
{
y = z;
}
else
{
y = Successor (z);
}
if (y->Left != &Nil)
{
x = y->Left;
}
else
{
x = y->Right;
}
x->Parent = y->Parent;
if (y->Parent == &Nil)
{
Root = x;
}
else if (y == y->Parent->Left)
{
y->Parent->Left = x;
}
else
{
y->Parent->Right = x;
}
if (y != z)
{
z->Distance = y->Distance;
z->Info = y->Info;
}
if (y->Color == FEvent::BLACK)
{
DeleteFixUp (x);
}
y->Left = Spare;
Spare = y;
}
void FEventTree::DeleteFixUp (FEvent *x)
{
FEvent *w;
while (x != Root && x->Color == FEvent::BLACK)
{
if (x == x->Parent->Left)
{
w = x->Parent->Right;
if (w->Color == FEvent::RED)
{
w->Color = FEvent::BLACK;
x->Parent->Color = FEvent::RED;
LeftRotate (x->Parent);
w = x->Parent->Right;
}
if (w->Left->Color == FEvent::BLACK && w->Right->Color == FEvent::BLACK)
{
w->Color = FEvent::RED;
x = x->Parent;
}
else
{
if (w->Right->Color == FEvent::BLACK)
{
w->Left->Color = FEvent::BLACK;
w->Color = FEvent::RED;
RightRotate (w);
w = x->Parent->Right;
}
w->Color = x->Parent->Color;
x->Parent->Color = FEvent::BLACK;
w->Right->Color = FEvent::BLACK;
LeftRotate (x->Parent);
x = Root;
}
}
else
{
w = x->Parent->Left;
if (w->Color == FEvent::RED)
{
w->Color = FEvent::BLACK;
x->Parent->Color = FEvent::RED;
RightRotate (x->Parent);
w = x->Parent->Left;
}
if (w->Right->Color == FEvent::BLACK && w->Left->Color == FEvent::BLACK)
{
w->Color = FEvent::RED;
x = x->Parent;
}
else
{
if (w->Left->Color == FEvent::BLACK)
{
w->Right->Color = FEvent::BLACK;
w->Color = FEvent::RED;
LeftRotate (w);
w = x->Parent->Left;
}
w->Color = x->Parent->Color;
x->Parent->Color = FEvent::BLACK;
w->Left->Color = FEvent::BLACK;
RightRotate (x->Parent);
x = Root;
}
}
}
}
FEvent *FEventTree::Successor (FEvent *event) const
@ -420,7 +199,7 @@ void FEventTree::PrintTree (const FEvent *event) const
{
PrintTree (event->Left);
}
printf (" Color %s, distance %g, vertex %d, seg %u\n", event->Color ? "BLACK" : " RED ",
printf (" Distance %g, vertex %d, seg %u\n",
sqrt(event->Distance/4294967296.0), event->Info.Vertex, event->Info.FrontSeg);
if (event->Right != &Nil)
{

View file

@ -236,8 +236,7 @@ void FNodeBuilder::GroupSegPlanes ()
D(printf ("%d planes from %d segs\n", planenum, Segs.Size()));
planenum = (planenum+7)/8;
PlaneChecked.Reserve (planenum);
PlaneChecked.Reserve ((planenum + 7) / 8);
}
// Find "loops" of segs surrounding polyobject's origin. Note that a polyobject's origin