From cf0d73b128facbdfede6c803c34a76b0e9d949fd Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Tue, 6 Jun 2006 05:00:46 +0000 Subject: [PATCH] - 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) --- main.cpp | 4 +- nodebuild.cpp | 29 ++++-- nodebuild.h | 5 - nodebuild_events.cpp | 223 +----------------------------------------- nodebuild_utility.cpp | 3 +- 5 files changed, 28 insertions(+), 236 deletions(-) diff --git a/main.cpp b/main.cpp index 12d1f1c..83f374e 100644 --- a/main.cpp +++ b/main.cpp @@ -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; } diff --git a/nodebuild.cpp b/nodebuild.cpp index 7b828be..225cbd9 100644 --- a/nodebuild.cpp +++ b/nodebuild.cpp @@ -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 diff --git a/nodebuild.h b/nodebuild.h index 68bd372..d847bd2 100644 --- a/nodebuild.h +++ b/nodebuild.h @@ -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; diff --git a/nodebuild_events.cpp b/nodebuild_events.cpp index cae2cd3..ecf7868 100644 --- a/nodebuild_events.cpp +++ b/nodebuild_events.cpp @@ -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) { diff --git a/nodebuild_utility.cpp b/nodebuild_utility.cpp index db21a3c..d1e777a 100644 --- a/nodebuild_utility.cpp +++ b/nodebuild_utility.cpp @@ -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